@ntlab/ntjs-assets 2.0.21 → 2.0.22

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 (402) hide show
  1. package/assets/js/cdn.json +1 -1
  2. package/assets/js/highcharts/css/highcharts.css +74 -0
  3. package/assets/js/highcharts/es-modules/Accessibility/Components/LegendComponent.js +1 -1
  4. package/assets/js/highcharts/es-modules/Accessibility/Components/SeriesComponent/SeriesComponent.js +1 -1
  5. package/assets/js/highcharts/es-modules/Accessibility/Components/SeriesComponent/SeriesKeyboardNavigation.js +9 -2
  6. package/assets/js/highcharts/es-modules/Core/Axis/Axis.js +25 -15
  7. package/assets/js/highcharts/es-modules/Core/Axis/AxisDefaults.js +3 -2
  8. package/assets/js/highcharts/es-modules/Core/Axis/Color/ColorAxis.js +1 -1
  9. package/assets/js/highcharts/es-modules/Core/Axis/Color/ColorAxisDefaults.js +2 -2
  10. package/assets/js/highcharts/es-modules/Core/Axis/GridAxis.js +1 -1
  11. package/assets/js/highcharts/es-modules/Core/Axis/OrdinalAxis.js +1 -1
  12. package/assets/js/highcharts/es-modules/Core/Axis/PlotLineOrBand/PlotLineOrBand.js +10 -0
  13. package/assets/js/highcharts/es-modules/Core/Axis/RadialAxis.js +19 -113
  14. package/assets/js/highcharts/es-modules/Core/Axis/RadialAxisDefaults.js +128 -0
  15. package/assets/js/highcharts/es-modules/Core/Axis/Tick.js +9 -13
  16. package/assets/js/highcharts/es-modules/Core/Chart/Chart.js +21 -17
  17. package/assets/js/highcharts/es-modules/Core/Chart/ChartDefaults.js +4 -2
  18. package/assets/js/highcharts/es-modules/Core/Chart/StockChart.js +5 -9
  19. package/assets/js/highcharts/es-modules/Core/Defaults.js +180 -91
  20. package/assets/js/highcharts/es-modules/Core/Renderer/SVG/SVGElement.js +50 -28
  21. package/assets/js/highcharts/es-modules/Core/Renderer/SVG/SVGLabel.js +6 -3
  22. package/assets/js/highcharts/es-modules/Core/Renderer/SVG/SVGRenderer.js +38 -80
  23. package/assets/js/highcharts/es-modules/Core/Renderer/SVG/Symbols.js +9 -5
  24. package/assets/js/highcharts/es-modules/Core/Series/DataLabel.js +17 -10
  25. package/assets/js/highcharts/es-modules/Core/Series/Point.js +4 -3
  26. package/assets/js/highcharts/es-modules/Core/Series/Series.js +24 -15
  27. package/assets/js/highcharts/es-modules/Core/Series/SeriesDefaults.js +15 -0
  28. package/assets/js/highcharts/es-modules/Core/Templating.js +4 -1
  29. package/assets/js/highcharts/es-modules/Core/Tooltip.js +17 -55
  30. package/assets/js/highcharts/es-modules/Core/Utilities.js +16 -0
  31. package/assets/js/highcharts/es-modules/Data/Converters/CSVConverter.js +1 -1
  32. package/assets/js/highcharts/es-modules/Data/DataCursor.js +34 -16
  33. package/assets/js/highcharts/es-modules/Data/DataPool.js +1 -1
  34. package/assets/js/highcharts/es-modules/Extensions/Annotations/Controllables/Controllable.js +3 -0
  35. package/assets/js/highcharts/es-modules/Extensions/Annotations/Controllables/ControllableLabel.js +0 -3
  36. package/assets/js/highcharts/es-modules/Extensions/Annotations/Controllables/ControllablePath.js +0 -3
  37. package/assets/js/highcharts/es-modules/Extensions/Annotations/EventEmitter.js +6 -6
  38. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/BasicAnnotation.js +2 -0
  39. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/CrookedLine.js +1 -0
  40. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/Fibonacci.js +4 -2
  41. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/FibonacciTimeZones.js +2 -1
  42. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/InfinityLine.js +2 -1
  43. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/Measure.js +4 -3
  44. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/Pitchfork.js +11 -5
  45. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/TimeCycles.js +2 -1
  46. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/Tunnel.js +4 -2
  47. package/assets/js/highcharts/es-modules/Extensions/Annotations/Types/VerticalLine.js +2 -1
  48. package/assets/js/highcharts/es-modules/Extensions/Boost/BoostChart.js +11 -3
  49. package/assets/js/highcharts/es-modules/Extensions/Boost/BoostSeries.js +7 -4
  50. package/assets/js/highcharts/es-modules/Extensions/Boost/WGLRenderer.js +11 -2
  51. package/assets/js/highcharts/es-modules/Extensions/Data.js +3 -3
  52. package/assets/js/highcharts/es-modules/Extensions/DataGrouping/DataGroupingSeriesComposition.js +1 -0
  53. package/assets/js/highcharts/es-modules/Extensions/DownloadURL.js +3 -0
  54. package/assets/js/highcharts/es-modules/Extensions/DragPanes/AxisResizer.js +1 -2
  55. package/assets/js/highcharts/es-modules/Extensions/DraggablePoints/DragDropProps.js +17 -0
  56. package/assets/js/highcharts/es-modules/Extensions/DraggablePoints/DraggablePoints.js +1 -0
  57. package/assets/js/highcharts/es-modules/Extensions/Drilldown/Drilldown.js +14 -14
  58. package/assets/js/highcharts/es-modules/Extensions/Exporting/Exporting.js +13 -18
  59. package/assets/js/highcharts/es-modules/Extensions/Exporting/ExportingDefaults.js +8 -6
  60. package/assets/js/highcharts/es-modules/Extensions/OfflineExporting/OfflineExporting.js +38 -30
  61. package/assets/js/highcharts/es-modules/Extensions/Pane/PaneDefaults.js +11 -0
  62. package/assets/js/highcharts/es-modules/Extensions/RegexLimits.js +1 -0
  63. package/assets/js/highcharts/es-modules/Extensions/ScrollablePlotArea.js +19 -17
  64. package/assets/js/highcharts/es-modules/Extensions/Themes/BrandDark.js +13 -1
  65. package/assets/js/highcharts/es-modules/Maps/MapNavigation.js +5 -3
  66. package/assets/js/highcharts/es-modules/Maps/MapView.js +5 -5
  67. package/assets/js/highcharts/es-modules/Maps/Projection.js +39 -20
  68. package/assets/js/highcharts/es-modules/Series/ArcDiagram/ArcDiagramSeries.js +10 -231
  69. package/assets/js/highcharts/es-modules/Series/ArcDiagram/ArcDiagramSeriesDefaults.js +245 -0
  70. package/assets/js/highcharts/es-modules/Series/Area/AreaSeries.js +2 -222
  71. package/assets/js/highcharts/es-modules/Series/Area/AreaSeriesDefaults.js +239 -0
  72. package/assets/js/highcharts/es-modules/Series/AreaRange/AreaRangeSeries.js +0 -133
  73. package/assets/js/highcharts/es-modules/Series/AreaRange/AreaRangeSeriesDefaults.js +273 -0
  74. package/assets/js/highcharts/es-modules/Series/BoxPlot/BoxPlotSeries.js +36 -38
  75. package/assets/js/highcharts/es-modules/Series/Bubble/BubbleSeries.js +17 -6
  76. package/assets/js/highcharts/es-modules/Series/Candlestick/CandlestickSeries.js +9 -11
  77. package/assets/js/highcharts/es-modules/Series/ColorMapComposition.js +28 -4
  78. package/assets/js/highcharts/es-modules/Series/Column/ColumnDataLabel.js +1 -1
  79. package/assets/js/highcharts/es-modules/Series/Column/ColumnSeries.js +25 -30
  80. package/assets/js/highcharts/es-modules/Series/DataModifyComposition.js +26 -2
  81. package/assets/js/highcharts/es-modules/Series/DotPlot/DotPlotSeries.js +37 -27
  82. package/assets/js/highcharts/es-modules/Series/DotPlot/DotPlotSeriesDefaults.js +3 -2
  83. package/assets/js/highcharts/es-modules/Series/Dumbbell/DumbbellSeries.js +1 -39
  84. package/assets/js/highcharts/es-modules/Series/Dumbbell/DumbbellSeriesDefaults.js +29 -0
  85. package/assets/js/highcharts/es-modules/Series/Flags/FlagsSeries.js +2 -1
  86. package/assets/js/highcharts/es-modules/Series/GeoHeatmap/GeoHeatmapSeries.js +3 -10
  87. package/assets/js/highcharts/es-modules/Series/HLC/HLCSeries.js +4 -5
  88. package/assets/js/highcharts/es-modules/Series/MapLine/MapLineSeriesDefaults.js +7 -6
  89. package/assets/js/highcharts/es-modules/Series/MapPoint/MapPointSeriesDefaults.js +17 -11
  90. package/assets/js/highcharts/es-modules/Series/Networkgraph/NetworkgraphSeriesDefaults.js +1 -1
  91. package/assets/js/highcharts/es-modules/Series/Networkgraph/ReingoldFruchtermanLayout.js +1 -1
  92. package/assets/js/highcharts/es-modules/Series/OHLC/OHLCSeries.js +3 -5
  93. package/assets/js/highcharts/es-modules/Series/Organization/OrganizationSeries.js +17 -19
  94. package/assets/js/highcharts/es-modules/Series/Organization/OrganizationSeriesDefaults.js +1 -1
  95. package/assets/js/highcharts/es-modules/Series/PackedBubble/PackedBubbleLayout.js +3 -3
  96. package/assets/js/highcharts/es-modules/Series/PackedBubble/PackedBubbleSeries.js +3 -3
  97. package/assets/js/highcharts/es-modules/Series/PackedBubble/PackedBubbleSeriesDefaults.js +0 -1
  98. package/assets/js/highcharts/es-modules/Series/Pyramid/PyramidSeriesDefaults.js +3 -3
  99. package/assets/js/highcharts/es-modules/Series/Sankey/SankeySeries.js +5 -6
  100. package/assets/js/highcharts/es-modules/Series/Sankey/SankeySeriesDefaults.js +1 -1
  101. package/assets/js/highcharts/es-modules/Series/SeriesOnPointComposition.js +2 -2
  102. package/assets/js/highcharts/es-modules/Series/Sunburst/SunburstSeriesDefaults.js +1 -1
  103. package/assets/js/highcharts/es-modules/Series/Treegraph/TreegraphLink.js +12 -7
  104. package/assets/js/highcharts/es-modules/Series/Treegraph/TreegraphSeries.js +8 -9
  105. package/assets/js/highcharts/es-modules/Series/Treemap/TreemapSeries.js +8 -8
  106. package/assets/js/highcharts/es-modules/Series/Treemap/TreemapSeriesDefaults.js +1 -1
  107. package/assets/js/highcharts/es-modules/Series/Variwide/VariwideSeries.js +4 -4
  108. package/assets/js/highcharts/es-modules/Series/Venn/VennSeriesDefaults.js +2 -2
  109. package/assets/js/highcharts/es-modules/Series/Waterfall/WaterfallSeries.js +11 -12
  110. package/assets/js/highcharts/es-modules/Series/XRange/XRangeSeries.js +4 -4
  111. package/assets/js/highcharts/es-modules/Stock/Navigator/Navigator.js +2 -5
  112. package/assets/js/highcharts/es-modules/Stock/Navigator/NavigatorDefaults.js +11 -0
  113. package/assets/js/highcharts/es-modules/Stock/Navigator/NavigatorSymbols.js +9 -10
  114. package/assets/js/highcharts/es-modules/Stock/RangeSelector/RangeSelector.js +162 -187
  115. package/assets/js/highcharts/es-modules/Stock/RangeSelector/RangeSelectorComposition.js +32 -74
  116. package/assets/js/highcharts/es-modules/Stock/Scrollbar/Scrollbar.js +6 -7
  117. package/assets/js/highcharts/es-modules/masters/highcharts-more.src.js +2 -0
  118. package/assets/js/highcharts/highcharts-3d.js +1 -1
  119. package/assets/js/highcharts/highcharts-3d.src.js +1 -1
  120. package/assets/js/highcharts/highcharts-gantt.js +3 -3
  121. package/assets/js/highcharts/highcharts-gantt.src.js +2008 -906
  122. package/assets/js/highcharts/highcharts-more.js +2 -2
  123. package/assets/js/highcharts/highcharts-more.src.js +234 -313
  124. package/assets/js/highcharts/highcharts.js +3 -3
  125. package/assets/js/highcharts/highcharts.src.js +743 -616
  126. package/assets/js/highcharts/highmaps.js +3 -3
  127. package/assets/js/highcharts/highmaps.src.js +862 -673
  128. package/assets/js/highcharts/highstock.js +3 -3
  129. package/assets/js/highcharts/highstock.src.js +1016 -935
  130. package/assets/js/highcharts/indicators/acceleration-bands.js +1 -1
  131. package/assets/js/highcharts/indicators/acceleration-bands.src.js +1 -1
  132. package/assets/js/highcharts/indicators/accumulation-distribution.js +1 -1
  133. package/assets/js/highcharts/indicators/accumulation-distribution.src.js +1 -1
  134. package/assets/js/highcharts/indicators/ao.js +1 -1
  135. package/assets/js/highcharts/indicators/ao.src.js +1 -1
  136. package/assets/js/highcharts/indicators/apo.js +1 -1
  137. package/assets/js/highcharts/indicators/apo.src.js +1 -1
  138. package/assets/js/highcharts/indicators/aroon-oscillator.js +1 -1
  139. package/assets/js/highcharts/indicators/aroon-oscillator.src.js +1 -1
  140. package/assets/js/highcharts/indicators/aroon.js +1 -1
  141. package/assets/js/highcharts/indicators/aroon.src.js +1 -1
  142. package/assets/js/highcharts/indicators/atr.js +1 -1
  143. package/assets/js/highcharts/indicators/atr.src.js +1 -1
  144. package/assets/js/highcharts/indicators/bollinger-bands.js +1 -1
  145. package/assets/js/highcharts/indicators/bollinger-bands.src.js +1 -1
  146. package/assets/js/highcharts/indicators/cci.js +1 -1
  147. package/assets/js/highcharts/indicators/cci.src.js +1 -1
  148. package/assets/js/highcharts/indicators/chaikin.js +1 -1
  149. package/assets/js/highcharts/indicators/chaikin.src.js +1 -1
  150. package/assets/js/highcharts/indicators/cmf.js +1 -1
  151. package/assets/js/highcharts/indicators/cmf.src.js +1 -1
  152. package/assets/js/highcharts/indicators/cmo.js +1 -1
  153. package/assets/js/highcharts/indicators/cmo.src.js +1 -1
  154. package/assets/js/highcharts/indicators/dema.js +1 -1
  155. package/assets/js/highcharts/indicators/dema.src.js +1 -1
  156. package/assets/js/highcharts/indicators/disparity-index.js +1 -1
  157. package/assets/js/highcharts/indicators/disparity-index.src.js +1 -1
  158. package/assets/js/highcharts/indicators/dmi.js +1 -1
  159. package/assets/js/highcharts/indicators/dmi.src.js +1 -1
  160. package/assets/js/highcharts/indicators/dpo.js +1 -1
  161. package/assets/js/highcharts/indicators/dpo.src.js +1 -1
  162. package/assets/js/highcharts/indicators/ichimoku-kinko-hyo.js +1 -1
  163. package/assets/js/highcharts/indicators/ichimoku-kinko-hyo.src.js +1 -1
  164. package/assets/js/highcharts/indicators/indicators-all.js +1 -1
  165. package/assets/js/highcharts/indicators/indicators-all.src.js +1 -1
  166. package/assets/js/highcharts/indicators/indicators.js +1 -1
  167. package/assets/js/highcharts/indicators/indicators.src.js +1 -1
  168. package/assets/js/highcharts/indicators/keltner-channels.js +1 -1
  169. package/assets/js/highcharts/indicators/keltner-channels.src.js +1 -1
  170. package/assets/js/highcharts/indicators/klinger.js +1 -1
  171. package/assets/js/highcharts/indicators/klinger.src.js +1 -1
  172. package/assets/js/highcharts/indicators/macd.js +1 -1
  173. package/assets/js/highcharts/indicators/macd.src.js +1 -1
  174. package/assets/js/highcharts/indicators/mfi.js +1 -1
  175. package/assets/js/highcharts/indicators/mfi.src.js +1 -1
  176. package/assets/js/highcharts/indicators/momentum.js +1 -1
  177. package/assets/js/highcharts/indicators/momentum.src.js +1 -1
  178. package/assets/js/highcharts/indicators/natr.js +1 -1
  179. package/assets/js/highcharts/indicators/natr.src.js +1 -1
  180. package/assets/js/highcharts/indicators/obv.js +1 -1
  181. package/assets/js/highcharts/indicators/obv.src.js +1 -1
  182. package/assets/js/highcharts/indicators/pivot-points.js +1 -1
  183. package/assets/js/highcharts/indicators/pivot-points.src.js +1 -1
  184. package/assets/js/highcharts/indicators/ppo.js +1 -1
  185. package/assets/js/highcharts/indicators/ppo.src.js +1 -1
  186. package/assets/js/highcharts/indicators/price-channel.js +1 -1
  187. package/assets/js/highcharts/indicators/price-channel.src.js +1 -1
  188. package/assets/js/highcharts/indicators/price-envelopes.js +1 -1
  189. package/assets/js/highcharts/indicators/price-envelopes.src.js +1 -1
  190. package/assets/js/highcharts/indicators/psar.js +1 -1
  191. package/assets/js/highcharts/indicators/psar.src.js +1 -1
  192. package/assets/js/highcharts/indicators/regressions.js +1 -1
  193. package/assets/js/highcharts/indicators/regressions.src.js +1 -1
  194. package/assets/js/highcharts/indicators/roc.js +1 -1
  195. package/assets/js/highcharts/indicators/roc.src.js +1 -1
  196. package/assets/js/highcharts/indicators/rsi.js +1 -1
  197. package/assets/js/highcharts/indicators/rsi.src.js +1 -1
  198. package/assets/js/highcharts/indicators/slow-stochastic.js +1 -1
  199. package/assets/js/highcharts/indicators/slow-stochastic.src.js +1 -1
  200. package/assets/js/highcharts/indicators/stochastic.js +1 -1
  201. package/assets/js/highcharts/indicators/stochastic.src.js +1 -1
  202. package/assets/js/highcharts/indicators/supertrend.js +1 -1
  203. package/assets/js/highcharts/indicators/supertrend.src.js +1 -1
  204. package/assets/js/highcharts/indicators/tema.js +1 -1
  205. package/assets/js/highcharts/indicators/tema.src.js +1 -1
  206. package/assets/js/highcharts/indicators/trendline.js +1 -1
  207. package/assets/js/highcharts/indicators/trendline.src.js +1 -1
  208. package/assets/js/highcharts/indicators/trix.js +1 -1
  209. package/assets/js/highcharts/indicators/trix.src.js +1 -1
  210. package/assets/js/highcharts/indicators/volume-by-price.js +1 -1
  211. package/assets/js/highcharts/indicators/volume-by-price.src.js +1 -1
  212. package/assets/js/highcharts/indicators/vwap.js +1 -1
  213. package/assets/js/highcharts/indicators/vwap.src.js +1 -1
  214. package/assets/js/highcharts/indicators/williams-r.js +1 -1
  215. package/assets/js/highcharts/indicators/williams-r.src.js +1 -1
  216. package/assets/js/highcharts/indicators/wma.js +1 -1
  217. package/assets/js/highcharts/indicators/wma.src.js +1 -1
  218. package/assets/js/highcharts/indicators/zigzag.js +1 -1
  219. package/assets/js/highcharts/indicators/zigzag.src.js +1 -1
  220. package/assets/js/highcharts/modules/accessibility.js +2 -2
  221. package/assets/js/highcharts/modules/accessibility.src.js +39 -28
  222. package/assets/js/highcharts/modules/annotations-advanced.js +2 -2
  223. package/assets/js/highcharts/modules/annotations-advanced.src.js +46 -31
  224. package/assets/js/highcharts/modules/annotations.js +2 -2
  225. package/assets/js/highcharts/modules/annotations.src.js +12 -15
  226. package/assets/js/highcharts/modules/arc-diagram.js +2 -2
  227. package/assets/js/highcharts/modules/arc-diagram.src.js +258 -233
  228. package/assets/js/highcharts/modules/arrow-symbols.js +1 -1
  229. package/assets/js/highcharts/modules/arrow-symbols.src.js +1 -1
  230. package/assets/js/highcharts/modules/boost-canvas.js +2 -2
  231. package/assets/js/highcharts/modules/boost-canvas.src.js +30 -10
  232. package/assets/js/highcharts/modules/boost.js +2 -2
  233. package/assets/js/highcharts/modules/boost.src.js +30 -10
  234. package/assets/js/highcharts/modules/broken-axis.js +1 -1
  235. package/assets/js/highcharts/modules/broken-axis.src.js +1 -1
  236. package/assets/js/highcharts/modules/bullet.js +1 -1
  237. package/assets/js/highcharts/modules/bullet.src.js +1 -1
  238. package/assets/js/highcharts/modules/coloraxis.js +2 -2
  239. package/assets/js/highcharts/modules/coloraxis.src.js +4 -4
  240. package/assets/js/highcharts/modules/current-date-indicator.js +1 -1
  241. package/assets/js/highcharts/modules/current-date-indicator.src.js +1 -1
  242. package/assets/js/highcharts/modules/cylinder.js +1 -1
  243. package/assets/js/highcharts/modules/cylinder.src.js +1 -1
  244. package/assets/js/highcharts/modules/data-tools.js +2 -2
  245. package/assets/js/highcharts/modules/data-tools.src.js +37 -19
  246. package/assets/js/highcharts/modules/data.js +1 -1
  247. package/assets/js/highcharts/modules/data.src.js +4 -4
  248. package/assets/js/highcharts/modules/datagrouping.js +2 -2
  249. package/assets/js/highcharts/modules/datagrouping.src.js +2 -1
  250. package/assets/js/highcharts/modules/debugger.js +1 -1
  251. package/assets/js/highcharts/modules/debugger.src.js +1 -1
  252. package/assets/js/highcharts/modules/dependency-wheel.js +1 -1
  253. package/assets/js/highcharts/modules/dependency-wheel.src.js +1 -1
  254. package/assets/js/highcharts/modules/dotplot.js +2 -2
  255. package/assets/js/highcharts/modules/dotplot.src.js +41 -30
  256. package/assets/js/highcharts/modules/drag-panes.js +2 -2
  257. package/assets/js/highcharts/modules/drag-panes.src.js +2 -3
  258. package/assets/js/highcharts/modules/draggable-points.js +2 -2
  259. package/assets/js/highcharts/modules/draggable-points.src.js +19 -1
  260. package/assets/js/highcharts/modules/drilldown.js +2 -2
  261. package/assets/js/highcharts/modules/drilldown.src.js +15 -15
  262. package/assets/js/highcharts/modules/dumbbell.js +2 -2
  263. package/assets/js/highcharts/modules/dumbbell.src.js +31 -40
  264. package/assets/js/highcharts/modules/export-data.js +2 -2
  265. package/assets/js/highcharts/modules/export-data.src.js +4 -1
  266. package/assets/js/highcharts/modules/exporting.js +2 -2
  267. package/assets/js/highcharts/modules/exporting.src.js +22 -25
  268. package/assets/js/highcharts/modules/flowmap.js +1 -1
  269. package/assets/js/highcharts/modules/flowmap.src.js +1 -1
  270. package/assets/js/highcharts/modules/full-screen.js +1 -1
  271. package/assets/js/highcharts/modules/full-screen.src.js +1 -1
  272. package/assets/js/highcharts/modules/funnel.js +2 -2
  273. package/assets/js/highcharts/modules/funnel.src.js +4 -4
  274. package/assets/js/highcharts/modules/funnel3d.js +1 -1
  275. package/assets/js/highcharts/modules/funnel3d.src.js +1 -1
  276. package/assets/js/highcharts/modules/gantt.js +2 -2
  277. package/assets/js/highcharts/modules/gantt.src.js +1266 -291
  278. package/assets/js/highcharts/modules/geoheatmap.js +1 -1
  279. package/assets/js/highcharts/modules/geoheatmap.src.js +4 -11
  280. package/assets/js/highcharts/modules/grid-axis.js +2 -2
  281. package/assets/js/highcharts/modules/grid-axis.src.js +2 -2
  282. package/assets/js/highcharts/modules/heatmap.js +2 -2
  283. package/assets/js/highcharts/modules/heatmap.src.js +32 -9
  284. package/assets/js/highcharts/modules/heikinashi.js +1 -1
  285. package/assets/js/highcharts/modules/heikinashi.src.js +1 -1
  286. package/assets/js/highcharts/modules/histogram-bellcurve.js +1 -1
  287. package/assets/js/highcharts/modules/histogram-bellcurve.src.js +1 -1
  288. package/assets/js/highcharts/modules/hollowcandlestick.js +1 -1
  289. package/assets/js/highcharts/modules/hollowcandlestick.src.js +1 -1
  290. package/assets/js/highcharts/modules/item-series.js +1 -1
  291. package/assets/js/highcharts/modules/item-series.src.js +1 -1
  292. package/assets/js/highcharts/modules/lollipop.js +1 -1
  293. package/assets/js/highcharts/modules/lollipop.src.js +1 -1
  294. package/assets/js/highcharts/modules/map.js +2 -2
  295. package/assets/js/highcharts/modules/map.src.js +120 -58
  296. package/assets/js/highcharts/modules/marker-clusters.js +1 -1
  297. package/assets/js/highcharts/modules/marker-clusters.src.js +1 -1
  298. package/assets/js/highcharts/modules/mouse-wheel-zoom.js +1 -1
  299. package/assets/js/highcharts/modules/mouse-wheel-zoom.src.js +1 -1
  300. package/assets/js/highcharts/modules/navigator.js +2 -2
  301. package/assets/js/highcharts/modules/navigator.src.js +28 -24
  302. package/assets/js/highcharts/modules/networkgraph.js +2 -2
  303. package/assets/js/highcharts/modules/networkgraph.src.js +3 -3
  304. package/assets/js/highcharts/modules/no-data-to-display.js +1 -1
  305. package/assets/js/highcharts/modules/no-data-to-display.src.js +1 -1
  306. package/assets/js/highcharts/modules/offline-exporting.js +2 -2
  307. package/assets/js/highcharts/modules/offline-exporting.src.js +43 -32
  308. package/assets/js/highcharts/modules/organization.js +2 -2
  309. package/assets/js/highcharts/modules/organization.src.js +19 -21
  310. package/assets/js/highcharts/modules/overlapping-datalabels.js +1 -1
  311. package/assets/js/highcharts/modules/overlapping-datalabels.src.js +1 -1
  312. package/assets/js/highcharts/modules/parallel-coordinates.js +1 -1
  313. package/assets/js/highcharts/modules/parallel-coordinates.src.js +1 -1
  314. package/assets/js/highcharts/modules/pareto.js +1 -1
  315. package/assets/js/highcharts/modules/pareto.src.js +1 -1
  316. package/assets/js/highcharts/modules/pathfinder.js +1 -1
  317. package/assets/js/highcharts/modules/pathfinder.src.js +1 -1
  318. package/assets/js/highcharts/modules/pattern-fill.js +1 -1
  319. package/assets/js/highcharts/modules/pattern-fill.src.js +1 -1
  320. package/assets/js/highcharts/modules/pictorial.js +1 -1
  321. package/assets/js/highcharts/modules/pictorial.src.js +1 -1
  322. package/assets/js/highcharts/modules/price-indicator.js +1 -1
  323. package/assets/js/highcharts/modules/price-indicator.src.js +1 -1
  324. package/assets/js/highcharts/modules/pyramid3d.js +1 -1
  325. package/assets/js/highcharts/modules/pyramid3d.src.js +1 -1
  326. package/assets/js/highcharts/modules/sankey.js +2 -2
  327. package/assets/js/highcharts/modules/sankey.src.js +7 -8
  328. package/assets/js/highcharts/modules/series-label.js +1 -1
  329. package/assets/js/highcharts/modules/series-label.src.js +1 -1
  330. package/assets/js/highcharts/modules/series-on-point.js +2 -2
  331. package/assets/js/highcharts/modules/series-on-point.src.js +3 -3
  332. package/assets/js/highcharts/modules/solid-gauge.js +1 -1
  333. package/assets/js/highcharts/modules/solid-gauge.src.js +1 -1
  334. package/assets/js/highcharts/modules/sonification.js +2 -2
  335. package/assets/js/highcharts/modules/sonification.src.js +4 -1
  336. package/assets/js/highcharts/modules/static-scale.js +1 -1
  337. package/assets/js/highcharts/modules/static-scale.src.js +1 -1
  338. package/assets/js/highcharts/modules/stock-tools.js +2 -2
  339. package/assets/js/highcharts/modules/stock-tools.src.js +3 -3
  340. package/assets/js/highcharts/modules/stock.js +2 -2
  341. package/assets/js/highcharts/modules/stock.src.js +274 -320
  342. package/assets/js/highcharts/modules/streamgraph.js +1 -1
  343. package/assets/js/highcharts/modules/streamgraph.src.js +1 -1
  344. package/assets/js/highcharts/modules/sunburst.js +2 -2
  345. package/assets/js/highcharts/modules/sunburst.src.js +39 -16
  346. package/assets/js/highcharts/modules/tiledwebmap.js +1 -1
  347. package/assets/js/highcharts/modules/tiledwebmap.src.js +1 -1
  348. package/assets/js/highcharts/modules/tilemap.js +1 -1
  349. package/assets/js/highcharts/modules/tilemap.src.js +1 -1
  350. package/assets/js/highcharts/modules/timeline.js +1 -1
  351. package/assets/js/highcharts/modules/timeline.src.js +1 -1
  352. package/assets/js/highcharts/modules/treegraph.js +2 -2
  353. package/assets/js/highcharts/modules/treegraph.src.js +21 -17
  354. package/assets/js/highcharts/modules/treegrid.js +2 -2
  355. package/assets/js/highcharts/modules/treegrid.src.js +2 -2
  356. package/assets/js/highcharts/modules/treemap.js +2 -2
  357. package/assets/js/highcharts/modules/treemap.src.js +38 -15
  358. package/assets/js/highcharts/modules/variable-pie.js +1 -1
  359. package/assets/js/highcharts/modules/variable-pie.src.js +1 -1
  360. package/assets/js/highcharts/modules/variwide.js +2 -2
  361. package/assets/js/highcharts/modules/variwide.src.js +5 -5
  362. package/assets/js/highcharts/modules/vector.js +1 -1
  363. package/assets/js/highcharts/modules/vector.src.js +1 -1
  364. package/assets/js/highcharts/modules/venn.js +1 -1
  365. package/assets/js/highcharts/modules/venn.src.js +3 -3
  366. package/assets/js/highcharts/modules/windbarb.js +1 -1
  367. package/assets/js/highcharts/modules/windbarb.src.js +1 -1
  368. package/assets/js/highcharts/modules/wordcloud.js +1 -1
  369. package/assets/js/highcharts/modules/wordcloud.src.js +1 -1
  370. package/assets/js/highcharts/modules/xrange.js +2 -2
  371. package/assets/js/highcharts/modules/xrange.src.js +5 -5
  372. package/assets/js/highcharts/standalone-navigator.js +2 -2
  373. package/assets/js/highcharts/standalone-navigator.src.js +769 -638
  374. package/assets/js/highcharts/themes/avocado.js +1 -1
  375. package/assets/js/highcharts/themes/avocado.src.js +1 -1
  376. package/assets/js/highcharts/themes/brand-dark.js +2 -2
  377. package/assets/js/highcharts/themes/brand-dark.src.js +14 -2
  378. package/assets/js/highcharts/themes/brand-light.js +1 -1
  379. package/assets/js/highcharts/themes/brand-light.src.js +1 -1
  380. package/assets/js/highcharts/themes/dark-blue.js +1 -1
  381. package/assets/js/highcharts/themes/dark-blue.src.js +1 -1
  382. package/assets/js/highcharts/themes/dark-green.js +1 -1
  383. package/assets/js/highcharts/themes/dark-green.src.js +1 -1
  384. package/assets/js/highcharts/themes/dark-unica.js +1 -1
  385. package/assets/js/highcharts/themes/dark-unica.src.js +1 -1
  386. package/assets/js/highcharts/themes/gray.js +1 -1
  387. package/assets/js/highcharts/themes/gray.src.js +1 -1
  388. package/assets/js/highcharts/themes/grid-light.js +1 -1
  389. package/assets/js/highcharts/themes/grid-light.src.js +1 -1
  390. package/assets/js/highcharts/themes/grid.js +1 -1
  391. package/assets/js/highcharts/themes/grid.src.js +1 -1
  392. package/assets/js/highcharts/themes/high-contrast-dark.js +1 -1
  393. package/assets/js/highcharts/themes/high-contrast-dark.src.js +1 -1
  394. package/assets/js/highcharts/themes/high-contrast-light.js +1 -1
  395. package/assets/js/highcharts/themes/high-contrast-light.src.js +1 -1
  396. package/assets/js/highcharts/themes/sand-signika.js +1 -1
  397. package/assets/js/highcharts/themes/sand-signika.src.js +1 -1
  398. package/assets/js/highcharts/themes/skies.js +1 -1
  399. package/assets/js/highcharts/themes/skies.src.js +1 -1
  400. package/assets/js/highcharts/themes/sunset.js +1 -1
  401. package/assets/js/highcharts/themes/sunset.src.js +1 -1
  402. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts Gantt JS v11.4.1 (2024-04-04)
2
+ * @license Highcharts Gantt JS v11.4.3 (2024-05-22)
3
3
  *
4
4
  * (c) 2017-2024 Lars Cabrera, Torstein Honsi, Jon Arild Nygard & Oystein Moseng
5
5
  *
@@ -62,7 +62,7 @@
62
62
  * Constants
63
63
  *
64
64
  * */
65
- Globals.SVG_NS = 'http://www.w3.org/2000/svg', Globals.product = 'Highcharts', Globals.version = '11.4.1', Globals.win = (typeof window !== 'undefined' ?
65
+ Globals.SVG_NS = 'http://www.w3.org/2000/svg', Globals.product = 'Highcharts', Globals.version = '11.4.3', Globals.win = (typeof window !== 'undefined' ?
66
66
  window :
67
67
  {}), // eslint-disable-line node/no-unsupported-features/es-builtins
68
68
  Globals.doc = Globals.win.document, Globals.svg = (Globals.doc &&
@@ -339,6 +339,21 @@
339
339
  function clamp(value, min, max) {
340
340
  return value > min ? value < max ? value : max : min;
341
341
  }
342
+ /**
343
+ * Utility for crisping a line position to the nearest full pixel depening on
344
+ * the line width
345
+ * @param {number} value The raw pixel position
346
+ * @param {number} lineWidth The line width
347
+ * @param {boolean} [inverted] Whether the containing group is inverted.
348
+ * Crisping round numbers on the y-scale need to go
349
+ * to the other side because the coordinate system
350
+ * is flipped (scaleY is -1)
351
+ * @return {number} The pixel position to use for a crisp display
352
+ */
353
+ const crisp = (value, lineWidth = 0, inverted) => {
354
+ const mod = lineWidth % 2 / 2, inverter = inverted ? -1 : 1;
355
+ return (Math.round(value * inverter - mod) + mod) * inverter;
356
+ };
342
357
  // eslint-disable-next-line valid-jsdoc
343
358
  /**
344
359
  * Return the deep difference between two objects. It can either return the new
@@ -1904,6 +1919,7 @@
1904
1919
  clearTimeout: internalClearTimeout,
1905
1920
  correctFloat,
1906
1921
  createElement,
1922
+ crisp,
1907
1923
  css,
1908
1924
  defined,
1909
1925
  destroyObjectProperties,
@@ -2692,7 +2708,7 @@
2692
2708
  *
2693
2709
  * @type {number}
2694
2710
  * @default 2
2695
- * @since @next
2711
+ * @since 11.3.0
2696
2712
  * @apioption chart.axisLayoutRuns
2697
2713
  */
2698
2714
  /**
@@ -3434,13 +3450,15 @@
3434
3450
  * element's height is 0.
3435
3451
  *
3436
3452
  * @sample {highcharts} highcharts/chart/height/
3437
- * 500px height
3453
+ * Forced 200px height
3438
3454
  * @sample {highstock} stock/chart/height/
3439
3455
  * 300px height
3440
3456
  * @sample {highmaps} maps/chart/size/
3441
3457
  * Chart with explicit size
3442
3458
  * @sample highcharts/chart/height-percent/
3443
3459
  * Highcharts with percentage height
3460
+ * @sample highcharts/chart/height-inherited/
3461
+ * Chart with inherited height
3444
3462
  *
3445
3463
  * @type {null|number|string}
3446
3464
  */
@@ -4339,8 +4357,8 @@
4339
4357
  * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
4340
4358
  *
4341
4359
  * */
4342
- const { isTouchDevice, svg } = H;
4343
- const { merge } = U;
4360
+ const { isTouchDevice } = H;
4361
+ const { fireEvent, merge } = U;
4344
4362
  /* *
4345
4363
  *
4346
4364
  * API Options
@@ -4571,84 +4589,163 @@
4571
4589
  * ```js
4572
4590
  * Highcharts.setOptions({
4573
4591
  * global: {
4574
- * useUTC: false
4592
+ * buttonTheme: {
4593
+ * fill: '#d0d0d0'
4594
+ * }
4575
4595
  * }
4576
4596
  * });
4577
4597
  * ```
4578
4598
  */
4579
- /**
4580
- * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\.
4581
- * Use the [libURL](#exporting.libURL) option to configure exporting._
4582
- *
4583
- * The URL to the additional file to lazy load for Android 2.x devices.
4584
- * These devices don't support SVG, so we download a helper file that
4585
- * contains [canvg](https://github.com/canvg/canvg), its dependency
4586
- * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to
4587
- * our site, you can install canvas-tools.js on your own server and
4588
- * change this option accordingly.
4589
- *
4590
- * @deprecated
4591
- *
4592
- * @type {string}
4593
- * @default https://code.highcharts.com/{version}/modules/canvas-tools.js
4594
- * @product highcharts highmaps
4595
- * @apioption global.canvasToolsURL
4596
- */
4597
- /**
4598
- * This option is deprecated since v6.0.5. Instead, use
4599
- * [time.useUTC](#time.useUTC) that supports individual time settings
4600
- * per chart.
4601
- *
4602
- * @deprecated
4603
- *
4604
- * @type {boolean}
4605
- * @apioption global.useUTC
4606
- */
4607
- /**
4608
- * This option is deprecated since v6.0.5. Instead, use
4609
- * [time.Date](#time.Date) that supports individual time settings
4610
- * per chart.
4611
- *
4612
- * @deprecated
4613
- *
4614
- * @type {Function}
4615
- * @product highcharts highstock
4616
- * @apioption global.Date
4617
- */
4618
- /**
4619
- * This option is deprecated since v6.0.5. Instead, use
4620
- * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports
4621
- * individual time settings per chart.
4622
- *
4623
- * @deprecated
4624
- *
4625
- * @type {Function}
4626
- * @product highcharts highstock
4627
- * @apioption global.getTimezoneOffset
4628
- */
4629
- /**
4630
- * This option is deprecated since v6.0.5. Instead, use
4631
- * [time.timezone](#time.timezone) that supports individual time
4632
- * settings per chart.
4633
- *
4634
- * @deprecated
4635
- *
4636
- * @type {string}
4637
- * @product highcharts highstock
4638
- * @apioption global.timezone
4639
- */
4640
- /**
4641
- * This option is deprecated since v6.0.5. Instead, use
4642
- * [time.timezoneOffset](#time.timezoneOffset) that supports individual
4643
- * time settings per chart.
4644
- *
4645
- * @deprecated
4646
- *
4647
- * @type {number}
4648
- * @product highcharts highstock
4649
- * @apioption global.timezoneOffset
4650
- */
4651
- global: {},
4599
+ global: {
4600
+ /**
4601
+ * _Canvg rendering for Android 2.x is removed as of Highcharts 5.0\.
4602
+ * Use the [libURL](#exporting.libURL) option to configure exporting._
4603
+ *
4604
+ * The URL to the additional file to lazy load for Android 2.x devices.
4605
+ * These devices don't support SVG, so we download a helper file that
4606
+ * contains [canvg](https://github.com/canvg/canvg), its dependency
4607
+ * rbcolor, and our own CanVG Renderer class. To avoid hotlinking to
4608
+ * our site, you can install canvas-tools.js on your own server and
4609
+ * change this option accordingly.
4610
+ *
4611
+ * @deprecated
4612
+ *
4613
+ * @type {string}
4614
+ * @default https://code.highcharts.com/{version}/modules/canvas-tools.js
4615
+ * @product highcharts highmaps
4616
+ * @apioption global.canvasToolsURL
4617
+ */
4618
+ /**
4619
+ * This option is deprecated since v6.0.5. Instead, use
4620
+ * [time.useUTC](#time.useUTC) that supports individual time settings
4621
+ * per chart.
4622
+ *
4623
+ * @deprecated
4624
+ *
4625
+ * @type {boolean}
4626
+ * @apioption global.useUTC
4627
+ */
4628
+ /**
4629
+ * This option is deprecated since v6.0.5. Instead, use
4630
+ * [time.Date](#time.Date) that supports individual time settings
4631
+ * per chart.
4632
+ *
4633
+ * @deprecated
4634
+ *
4635
+ * @type {Function}
4636
+ * @product highcharts highstock
4637
+ * @apioption global.Date
4638
+ */
4639
+ /**
4640
+ * This option is deprecated since v6.0.5. Instead, use
4641
+ * [time.getTimezoneOffset](#time.getTimezoneOffset) that supports
4642
+ * individual time settings per chart.
4643
+ *
4644
+ * @deprecated
4645
+ *
4646
+ * @type {Function}
4647
+ * @product highcharts highstock
4648
+ * @apioption global.getTimezoneOffset
4649
+ */
4650
+ /**
4651
+ * This option is deprecated since v6.0.5. Instead, use
4652
+ * [time.timezone](#time.timezone) that supports individual time
4653
+ * settings per chart.
4654
+ *
4655
+ * @deprecated
4656
+ *
4657
+ * @type {string}
4658
+ * @product highcharts highstock
4659
+ * @apioption global.timezone
4660
+ */
4661
+ /**
4662
+ * This option is deprecated since v6.0.5. Instead, use
4663
+ * [time.timezoneOffset](#time.timezoneOffset) that supports individual
4664
+ * time settings per chart.
4665
+ *
4666
+ * @deprecated
4667
+ *
4668
+ * @type {number}
4669
+ * @product highcharts highstock
4670
+ * @apioption global.timezoneOffset
4671
+ */
4672
+ /**
4673
+ * General theme for buttons. This applies to the zoom button, exporting
4674
+ * context menu, map navigation, range selector buttons and custom
4675
+ * buttons generated using the `SVGRenderer.button` function. However,
4676
+ * each of these may be overridden with more specific options.
4677
+ *
4678
+ * @sample highcharts/global/buttontheme
4679
+ * General button theme
4680
+ * @since 11.4.2
4681
+ */
4682
+ buttonTheme: {
4683
+ /**
4684
+ * The fill color for buttons
4685
+ */
4686
+ fill: "#f7f7f7" /* Palette.neutralColor3 */,
4687
+ /**
4688
+ * The padding of buttons
4689
+ */
4690
+ padding: 8,
4691
+ /**
4692
+ * The border radius for buttons
4693
+ */
4694
+ r: 2,
4695
+ /**
4696
+ * The stroke color for buttons
4697
+ */
4698
+ stroke: "#cccccc" /* Palette.neutralColor20 */,
4699
+ /**
4700
+ * The stroke width for buttons
4701
+ */
4702
+ 'stroke-width': 1,
4703
+ /**
4704
+ * CSS styling for the buttons' text
4705
+ */
4706
+ style: {
4707
+ color: "#333333" /* Palette.neutralColor80 */,
4708
+ cursor: 'pointer',
4709
+ fontSize: '0.8em',
4710
+ fontWeight: 'normal'
4711
+ },
4712
+ /**
4713
+ * State overrides for the buttons
4714
+ */
4715
+ states: {
4716
+ /**
4717
+ * Hover state overrides for the buttons are applied in addition
4718
+ * to the normal state options
4719
+ */
4720
+ hover: {
4721
+ fill: "#e6e6e6" /* Palette.neutralColor10 */
4722
+ },
4723
+ /**
4724
+ * Select state overrides for the buttons are applied in
4725
+ * addition to the normal state options
4726
+ */
4727
+ select: {
4728
+ fill: "#e6e9ff" /* Palette.highlightColor10 */,
4729
+ style: {
4730
+ color: "#000000" /* Palette.neutralColor100 */,
4731
+ fontWeight: 'bold'
4732
+ }
4733
+ },
4734
+ /**
4735
+ * Disabled state overrides for the buttons are applied in
4736
+ * addition to the normal state options
4737
+ */
4738
+ disabled: {
4739
+ /**
4740
+ * Disabled state CSS style overrides for the buttons' text
4741
+ */
4742
+ style: {
4743
+ color: "#cccccc" /* Palette.neutralColor20 */
4744
+ }
4745
+ }
4746
+ }
4747
+ }
4748
+ },
4652
4749
  /**
4653
4750
  * Time options that can apply globally or to individual charts. These
4654
4751
  * settings affect how `datetime` axes are laid out, how tooltips are
@@ -4718,13 +4815,16 @@
4718
4815
  * for drawing time based charts in specific time zones using their
4719
4816
  * local DST crossover dates, with the help of external libraries.
4720
4817
  *
4721
- * @see [global.timezoneOffset](#global.timezoneOffset)
4818
+ * This option is deprecated as of v11.4.1 and will be removed in a
4819
+ * future release. Use the [time.timezone](#time.timezone) option
4820
+ * instead.
4722
4821
  *
4723
4822
  * @sample {highcharts|highstock} highcharts/time/gettimezoneoffset/
4724
4823
  * Use moment.js to draw Oslo time regardless of browser locale
4725
4824
  *
4726
4825
  * @type {Highcharts.TimezoneOffsetCallbackFunction}
4727
4826
  * @since 4.1.0
4827
+ * @deprecated 11.4.2
4728
4828
  * @product highcharts highstock gantt
4729
4829
  */
4730
4830
  getTimezoneOffset: void 0,
@@ -4734,12 +4834,10 @@
4734
4834
  * docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#timezone).
4735
4835
  * If the given time zone is not recognized by the browser, Highcharts
4736
4836
  * provides a warning and falls back to returning a 0 offset,
4737
- * corresponding to the UCT time zone.
4837
+ * corresponding to the UTC time zone.
4738
4838
  *
4739
4839
  * Until v11.2.0, this option depended on moment.js.
4740
4840
  *
4741
- * @see [getTimezoneOffset](#time.getTimezoneOffset)
4742
- *
4743
4841
  * @sample {highcharts|highstock} highcharts/time/timezone/ Europe/Oslo
4744
4842
  *
4745
4843
  * @type {string}
@@ -4753,12 +4851,17 @@
4753
4851
  * [getTimezoneOffset](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset)
4754
4852
  * method. Use this to display UTC based data in a predefined time zone.
4755
4853
  *
4854
+ * This option is deprecated as of v11.4.1 and will be removed in a
4855
+ * future release. Use the [time.timezone](#time.timezone) option
4856
+ * instead.
4857
+ *
4756
4858
  * @see [time.getTimezoneOffset](#time.getTimezoneOffset)
4757
4859
  *
4758
4860
  * @sample {highcharts|highstock} highcharts/time/timezoneoffset/
4759
4861
  * Timezone offset
4760
4862
  *
4761
4863
  * @since 3.0.8
4864
+ * @deprecated 11.4.2
4762
4865
  * @product highcharts highstock gantt
4763
4866
  */
4764
4867
  timezoneOffset: 0,
@@ -5644,7 +5747,7 @@
5644
5747
  * Item text styles
5645
5748
  *
5646
5749
  * @type {Highcharts.CSSObject}
5647
- * @default {"color": "#333333", "cursor": "pointer", "fontSize": "0.75em", "fontWeight": "bold", "textOverflow": "ellipsis"}
5750
+ * @default {"color": "#333333", "cursor": "pointer", "fontSize": "0.8em", "fontWeight": "bold", "textOverflow": "ellipsis"}
5648
5751
  */
5649
5752
  itemStyle: {
5650
5753
  /**
@@ -5956,7 +6059,7 @@
5956
6059
  * `.highcharts-legend-title` class.
5957
6060
  *
5958
6061
  * @type {Highcharts.CSSObject}
5959
- * @default {"fontSize": "0.75em", "fontWeight": "bold"}
6062
+ * @default {"fontSize": "0.8em", "fontWeight": "bold"}
5960
6063
  * @since 3.0
5961
6064
  */
5962
6065
  style: {
@@ -6163,20 +6266,20 @@
6163
6266
  */
6164
6267
  /**
6165
6268
  * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
6166
- * for the whole tooltip. When format strings are a requirement, it is
6167
- * usually more convenient to use `headerFormat`, `pointFormat` and
6168
- * `footerFormat`, but the `format` option allows combining them into
6169
- * one setting.
6269
+ * for the whole shared tooltip. When format strings are a requirement,
6270
+ * it is usually more convenient to use `headerFormat`, `pointFormat`
6271
+ * and `footerFormat`, but the `format` option allows combining them
6272
+ * into one setting.
6170
6273
  *
6171
6274
  * The context of the format string is the same as that of the
6172
- * `formatter` callback.
6275
+ * `tooltip.formatter` callback.
6173
6276
  *
6174
6277
  * @sample {highcharts} highcharts/tooltip/format-shared/
6175
6278
  * Format for shared tooltip
6176
6279
  *
6177
6280
  * @type {string}
6178
6281
  * @default undefined
6179
- * @since 11.1.0
6282
+ * @since 11.1.0
6180
6283
  * @apioption tooltip.format
6181
6284
  */
6182
6285
  /**
@@ -6449,11 +6552,14 @@
6449
6552
  /**
6450
6553
  * Enable or disable animation of the tooltip.
6451
6554
  *
6452
- * @type {boolean}
6453
- * @default true
6555
+ * @type {boolean|Partial<Highcharts.AnimationOptionsObject>}
6454
6556
  * @since 2.3.0
6455
6557
  */
6456
- animation: svg,
6558
+ animation: {
6559
+ duration: 300,
6560
+ // EaseOutCirc
6561
+ easing: (x) => Math.sqrt(1 - Math.pow(x - 1, 2))
6562
+ },
6457
6563
  /**
6458
6564
  * The radius of the rounded border corners.
6459
6565
  *
@@ -6908,6 +7014,7 @@
6908
7014
  * Updated options.
6909
7015
  */
6910
7016
  function setOptions(options) {
7017
+ fireEvent(H, 'setOptions', { options });
6911
7018
  // Copy in the default options
6912
7019
  merge(true, defaultOptions, options);
6913
7020
  // Update the time object
@@ -8857,7 +8964,7 @@
8857
8964
  // Block helpers may return true or false. They may also return a
8858
8965
  // string, like the `each` helper.
8859
8966
  if (match.isBlock && typeof replacement === 'boolean') {
8860
- replacement = format(replacement ? body : elseBody, ctx);
8967
+ replacement = format(replacement ? body : elseBody, ctx, chart);
8861
8968
  }
8862
8969
  // Simple variable replacement
8863
8970
  }
@@ -8974,6 +9081,9 @@
8974
9081
  // Get the decimal component
8975
9082
  ret += decimalPoint + roundedNumber.slice(-decimals);
8976
9083
  }
9084
+ else if (+ret === 0) { // Remove signed minus #20564
9085
+ ret = '0';
9086
+ }
8977
9087
  if (exponent[1] && +ret !== 0) {
8978
9088
  ret += 'e' + exponent[1];
8979
9089
  }
@@ -9255,7 +9365,7 @@
9255
9365
  * */
9256
9366
  const { animate, animObject, stop } = A;
9257
9367
  const { deg2rad, doc, svg, SVG_NS, win } = H;
9258
- const { addEvent, attr, createElement, css, defined, erase, extend, fireEvent, isArray, isFunction, isObject, isString, merge, objectEach, pick, pInt, replaceNested, syncTimeout, uniqueKey } = U;
9368
+ const { addEvent, attr, createElement, crisp, css, defined, erase, extend, fireEvent, isArray, isFunction, isObject, isString, merge, objectEach, pick, pInt, pushUnique, replaceNested, syncTimeout, uniqueKey } = U;
9259
9369
  /* *
9260
9370
  *
9261
9371
  * Class
@@ -9441,7 +9551,7 @@
9441
9551
  * @param {boolean} [alignByTranslate]
9442
9552
  * Align element by translation.
9443
9553
  *
9444
- * @param {string|Highcharts.BBoxObject} [box]
9554
+ * @param {string|Highcharts.BBoxObject} [alignTo]
9445
9555
  * The box to align to, needs a width and height. When the box is a
9446
9556
  * string, it refers to an object in the Renderer. For example, when
9447
9557
  * box is `spacingBox`, it refers to `Renderer.spacingBox` which
@@ -9453,34 +9563,39 @@
9453
9563
  *
9454
9564
  * @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
9455
9565
  */
9456
- align(alignOptions, alignByTranslate, box, redraw = true) {
9457
- const attribs = {}, renderer = this.renderer, alignedObjects = renderer.alignedObjects;
9458
- let x, y, alignTo, alignFactor, vAlignFactor;
9566
+ align(alignOptions, alignByTranslate, alignTo, redraw = true) {
9567
+ const attribs = {}, renderer = this.renderer, alignedObjects = renderer.alignedObjects, initialAlignment = Boolean(alignOptions);
9568
+ let x, y, alignFactor, vAlignFactor;
9459
9569
  // First call on instanciate
9460
9570
  if (alignOptions) {
9461
9571
  this.alignOptions = alignOptions;
9462
9572
  this.alignByTranslate = alignByTranslate;
9463
- if (!box || isString(box)) {
9464
- this.alignTo = alignTo = box || 'renderer';
9465
- // Prevent duplicates, like legendGroup after resize
9466
- erase(alignedObjects, this);
9467
- alignedObjects.push(this);
9468
- box = void 0; // Reassign it below
9469
- }
9573
+ this.alignTo = alignTo;
9470
9574
  // When called on resize, no arguments are supplied
9471
9575
  }
9472
9576
  else {
9473
- alignOptions = this.alignOptions;
9577
+ alignOptions = this.alignOptions || {};
9474
9578
  alignByTranslate = this.alignByTranslate;
9475
9579
  alignTo = this.alignTo;
9476
9580
  }
9477
- box = pick(box, renderer[alignTo], renderer);
9581
+ const alignToKey = !alignTo || isString(alignTo) ?
9582
+ alignTo || 'renderer' :
9583
+ void 0;
9584
+ // When aligned to a key, automatically re-align on redraws
9585
+ if (alignToKey) {
9586
+ // Prevent duplicates, like legendGroup after resize
9587
+ if (initialAlignment) {
9588
+ pushUnique(alignedObjects, this);
9589
+ }
9590
+ alignTo = void 0; // Do not use the box
9591
+ }
9592
+ const alignToBox = pick(alignTo, renderer[alignToKey], renderer);
9478
9593
  // Assign variables
9479
9594
  const align = alignOptions.align, vAlign = alignOptions.verticalAlign;
9480
9595
  // Default: left align
9481
- x = (box.x || 0) + (alignOptions.x || 0);
9596
+ x = (alignToBox.x || 0) + (alignOptions.x || 0);
9482
9597
  // Default: top align
9483
- y = (box.y || 0) + (alignOptions.y || 0);
9598
+ y = (alignToBox.y || 0) + (alignOptions.y || 0);
9484
9599
  // Align
9485
9600
  if (align === 'right') {
9486
9601
  alignFactor = 1;
@@ -9489,7 +9604,7 @@
9489
9604
  alignFactor = 2;
9490
9605
  }
9491
9606
  if (alignFactor) {
9492
- x += (box.width - (alignOptions.width || 0)) /
9607
+ x += ((alignToBox.width || 0) - (alignOptions.width || 0)) /
9493
9608
  alignFactor;
9494
9609
  }
9495
9610
  attribs[alignByTranslate ? 'translateX' : 'x'] = Math.round(x);
@@ -9501,7 +9616,7 @@
9501
9616
  vAlignFactor = 2;
9502
9617
  }
9503
9618
  if (vAlignFactor) {
9504
- y += (box.height - (alignOptions.height || 0)) /
9619
+ y += ((alignToBox.height || 0) - (alignOptions.height || 0)) /
9505
9620
  vAlignFactor;
9506
9621
  }
9507
9622
  attribs[alignByTranslate ? 'translateY' : 'y'] = Math.round(y);
@@ -9721,7 +9836,7 @@
9721
9836
  * used as a getter, the current value of the attribute is returned.
9722
9837
  */
9723
9838
  attr(hash, val, complete, continueAnimation) {
9724
- const element = this.element, symbolCustomAttribs = SVGElement.symbolCustomAttribs;
9839
+ const { element } = this, symbolCustomAttribs = SVGElement.symbolCustomAttribs;
9725
9840
  let key, hasSetSymbolSize, ret = this, skipAttr, setter;
9726
9841
  // Single key-value pair
9727
9842
  if (typeof hash === 'string' && typeof val !== 'undefined') {
@@ -9811,15 +9926,17 @@
9811
9926
  * The modified rectangle arguments.
9812
9927
  */
9813
9928
  crisp(rect, strokeWidth) {
9814
- const wrapper = this;
9815
- strokeWidth = strokeWidth || rect.strokeWidth || 0;
9816
9929
  // Math.round because strokeWidth can sometimes have roundoff errors
9817
- const normalizer = Math.round(strokeWidth) % 2 / 2;
9818
- // Normalize for crisp edges
9819
- rect.x = Math.floor(rect.x || wrapper.x || 0) + normalizer;
9820
- rect.y = Math.floor(rect.y || wrapper.y || 0) + normalizer;
9821
- rect.width = Math.floor((rect.width || wrapper.width || 0) - 2 * normalizer);
9822
- rect.height = Math.floor((rect.height || wrapper.height || 0) - 2 * normalizer);
9930
+ strokeWidth = Math.round(strokeWidth || rect.strokeWidth || 0);
9931
+ const x1 = rect.x || this.x || 0, y1 = rect.y || this.y || 0, x2 = (rect.width || this.width || 0) + x1, y2 = (rect.height || this.height || 0) + y1,
9932
+ // Find all the rounded coordinates for corners
9933
+ x = crisp(x1, strokeWidth), y = crisp(y1, strokeWidth), x2Crisp = crisp(x2, strokeWidth), y2Crisp = crisp(y2, strokeWidth);
9934
+ extend(rect, {
9935
+ x,
9936
+ y,
9937
+ width: x2Crisp - x,
9938
+ height: y2Crisp - y
9939
+ });
9823
9940
  if (defined(rect.strokeWidth)) {
9824
9941
  rect.strokeWidth = strokeWidth;
9825
9942
  }
@@ -10094,7 +10211,7 @@
10094
10211
  parentToClean = grandParent;
10095
10212
  }
10096
10213
  // Remove from alignObjects
10097
- if (wrapper.alignTo) {
10214
+ if (wrapper.alignOptions) {
10098
10215
  erase(renderer.alignedObjects, wrapper);
10099
10216
  }
10100
10217
  objectEach(wrapper, function (val, key) {
@@ -10469,6 +10586,20 @@
10469
10586
  this.opacity = opacity;
10470
10587
  element.setAttribute(key, opacity);
10471
10588
  }
10589
+ /**
10590
+ * Re-align an aligned text or label after setting the text.
10591
+ *
10592
+ * @private
10593
+ * @function Highcharts.SVGElement#reAlign
10594
+ *
10595
+ */
10596
+ reAlign() {
10597
+ if (this.alignOptions?.width && this.alignOptions.align !== 'left') {
10598
+ this.alignOptions.width = this.getBBox().width;
10599
+ this.placed = false; // Block animation
10600
+ this.align();
10601
+ }
10602
+ }
10472
10603
  /**
10473
10604
  * Remove a class name from the element.
10474
10605
  *
@@ -10768,6 +10899,7 @@
10768
10899
  if (this.added) {
10769
10900
  this.renderer.buildText(this);
10770
10901
  }
10902
+ this.reAlign();
10771
10903
  }
10772
10904
  }
10773
10905
  /**
@@ -11360,9 +11492,11 @@
11360
11492
  return bBox;
11361
11493
  }
11362
11494
  getCrispAdjust() {
11363
- return this.renderer.styledMode && this.box ?
11364
- this.box.strokeWidth() % 2 / 2 :
11365
- (this['stroke-width'] ? parseInt(this['stroke-width'], 10) : 0) % 2 / 2;
11495
+ return (this.renderer.styledMode && this.box ?
11496
+ this.box.strokeWidth() :
11497
+ (this['stroke-width'] ?
11498
+ parseInt(this['stroke-width'], 10) :
11499
+ 0)) % 2 / 2;
11366
11500
  }
11367
11501
  heightSetter(value) {
11368
11502
  this.heightSetting = value;
@@ -11420,6 +11554,7 @@
11420
11554
  this.text.attr({ text });
11421
11555
  }
11422
11556
  this.updateTextPadding();
11557
+ this.reAlign();
11423
11558
  }
11424
11559
  /*
11425
11560
  * This function runs after the label is added to the DOM (when the bounding
@@ -11591,11 +11726,15 @@
11591
11726
  function arc(cx, cy, w, h, options) {
11592
11727
  const arc = [];
11593
11728
  if (options) {
11594
- const start = options.start || 0, rx = pick(options.r, w), ry = pick(options.r, h || w), proximity = 0.001, fullCircle = (Math.abs((options.end || 0) - start - 2 * Math.PI) <
11595
- proximity),
11596
- // Subtract a small number to prevent cos and sin of start
11597
- // and end from becoming equal on 360 arcs (related: #1561)
11598
- end = (options.end || 0) - proximity, innerRadius = options.innerR, open = pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end),
11729
+ const start = options.start || 0, rx = pick(options.r, w), ry = pick(options.r, h || w),
11730
+ // Subtract a small number to prevent cos and sin of start and end
11731
+ // from becoming equal on 360 arcs (#1561). The size of the circle
11732
+ // affects the constant, therefore the division by `rx`. If the
11733
+ // proximity is too small, the arc disappears. If it is too great, a
11734
+ // gap appears. This can be seen in the animation of the official
11735
+ // bubble demo (#20586).
11736
+ proximity = 0.0002 / Math.max(rx, 1), fullCircle = (Math.abs((options.end || 0) - start - 2 * Math.PI) <
11737
+ proximity), end = (options.end || 0) - proximity, innerRadius = options.innerR, open = pick(options.open, fullCircle), cosStart = Math.cos(start), sinStart = Math.sin(start), cosEnd = Math.cos(end), sinEnd = Math.sin(end),
11599
11738
  // Proximity takes care of rounding errors around PI (#6971)
11600
11739
  longArc = pick(options.longArc, end - start - Math.PI < proximity ? 0 : 1);
11601
11740
  let arcSegment = [
@@ -12243,7 +12382,7 @@
12243
12382
 
12244
12383
  return TextBuilder;
12245
12384
  });
12246
- _registerModule(_modules, 'Core/Renderer/SVG/SVGRenderer.js', [_modules['Core/Renderer/HTML/AST.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Renderer/RendererRegistry.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Renderer/SVG/SVGLabel.js'], _modules['Core/Renderer/SVG/Symbols.js'], _modules['Core/Renderer/SVG/TextBuilder.js'], _modules['Core/Utilities.js']], function (AST, Color, H, RendererRegistry, SVGElement, SVGLabel, Symbols, TextBuilder, U) {
12385
+ _registerModule(_modules, 'Core/Renderer/SVG/SVGRenderer.js', [_modules['Core/Renderer/HTML/AST.js'], _modules['Core/Defaults.js'], _modules['Core/Color/Color.js'], _modules['Core/Globals.js'], _modules['Core/Renderer/RendererRegistry.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Renderer/SVG/SVGLabel.js'], _modules['Core/Renderer/SVG/Symbols.js'], _modules['Core/Renderer/SVG/TextBuilder.js'], _modules['Core/Utilities.js']], function (AST, D, Color, H, RendererRegistry, SVGElement, SVGLabel, Symbols, TextBuilder, U) {
12247
12386
  /* *
12248
12387
  *
12249
12388
  * (c) 2010-2024 Torstein Honsi
@@ -12253,8 +12392,9 @@
12253
12392
  * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
12254
12393
  *
12255
12394
  * */
12395
+ const { defaultOptions } = D;
12256
12396
  const { charts, deg2rad, doc, isFirefox, isMS, isWebKit, noop, SVG_NS, symbolSizes, win } = H;
12257
- const { addEvent, attr, createElement, css, defined, destroyObjectProperties, extend, isArray, isNumber, isObject, isString, merge, pick, pInt, replaceNested, uniqueKey } = U;
12397
+ const { addEvent, attr, createElement, crisp, css, defined, destroyObjectProperties, extend, isArray, isNumber, isObject, isString, merge, pick, pInt, replaceNested, uniqueKey } = U;
12258
12398
  /* *
12259
12399
  *
12260
12400
  * Variables
@@ -12403,7 +12543,7 @@
12403
12543
  this.url = this.getReferenceURL();
12404
12544
  // Add description
12405
12545
  const desc = this.createElement('desc').add();
12406
- desc.element.appendChild(doc.createTextNode('Created with Highcharts 11.4.1'));
12546
+ desc.element.appendChild(doc.createTextNode('Created with Highcharts 11.4.3'));
12407
12547
  this.defs = this.createElement('defs').add();
12408
12548
  this.allowHTML = allowHTML;
12409
12549
  this.forExport = forExport;
@@ -12736,7 +12876,9 @@
12736
12876
  return 1.05 / (l + 0.05) > (l + 0.05) / 0.05 ? '#FFFFFF' : '#000000';
12737
12877
  }
12738
12878
  /**
12739
- * Create a button with preset states.
12879
+ * Create a button with preset states. Styles for the button can either be
12880
+ * set as arguments, or a general theme for all buttons can be set by the
12881
+ * `global.buttonTheme` option.
12740
12882
  *
12741
12883
  * @function Highcharts.SVGRenderer#button
12742
12884
  *
@@ -12774,56 +12916,31 @@
12774
12916
  * The button element.
12775
12917
  */
12776
12918
  button(text, x, y, callback, theme = {}, hoverState, selectState, disabledState, shape, useHTML) {
12777
- const label = this.label(text, x, y, shape, void 0, void 0, useHTML, void 0, 'button'), styledMode = this.styledMode, states = theme.states || {};
12919
+ const label = this.label(text, x, y, shape, void 0, void 0, useHTML, void 0, 'button'), styledMode = this.styledMode, args = arguments;
12778
12920
  let curState = 0;
12779
- theme = merge(theme);
12921
+ theme = merge(defaultOptions.global.buttonTheme, theme);
12922
+ // @todo Consider moving this to a lower level, like .attr
12923
+ if (styledMode) {
12924
+ delete theme.fill;
12925
+ delete theme.stroke;
12926
+ delete theme['stroke-width'];
12927
+ }
12928
+ const states = theme.states || {}, normalStyle = theme.style || {};
12780
12929
  delete theme.states;
12781
- const normalStyle = merge({
12782
- color: "#333333" /* Palette.neutralColor80 */,
12783
- cursor: 'pointer',
12784
- fontSize: '0.8em',
12785
- fontWeight: 'normal'
12786
- }, theme.style);
12787
12930
  delete theme.style;
12788
- // Remove stylable attributes. Pass in the ButtonThemeObject and get the
12789
- // SVGAttributes subset back.
12790
- let normalState = AST.filterUserAttributes(theme);
12791
- // Default, non-stylable attributes
12792
- label.attr(merge({ padding: 8, r: 2 }, normalState));
12793
- // Presentational. The string type is a mistake, it is just for
12794
- // compliance with SVGAttribute and is not used in button theme.
12795
- let hoverStyle, selectStyle, disabledStyle;
12931
+ // Presentational
12932
+ const stateAttribs = [
12933
+ AST.filterUserAttributes(theme)
12934
+ ],
12935
+ // The string type is a mistake, it is just for compliance with
12936
+ // SVGAttribute and is not used in button theme.
12937
+ stateStyles = [normalStyle];
12796
12938
  if (!styledMode) {
12797
- // Normal state - prepare the attributes
12798
- normalState = merge({
12799
- fill: "#f7f7f7" /* Palette.neutralColor3 */,
12800
- stroke: "#cccccc" /* Palette.neutralColor20 */,
12801
- 'stroke-width': 1
12802
- }, normalState);
12803
- // Hover state
12804
- hoverState = merge(normalState, {
12805
- fill: "#e6e6e6" /* Palette.neutralColor10 */
12806
- }, AST.filterUserAttributes(hoverState || states.hover || {}));
12807
- hoverStyle = hoverState.style;
12808
- delete hoverState.style;
12809
- // Pressed state
12810
- selectState = merge(normalState, {
12811
- fill: "#e6e9ff" /* Palette.highlightColor10 */,
12812
- style: {
12813
- color: "#000000" /* Palette.neutralColor100 */,
12814
- fontWeight: 'bold'
12815
- }
12816
- }, AST.filterUserAttributes(selectState || states.select || {}));
12817
- selectStyle = selectState.style;
12818
- delete selectState.style;
12819
- // Disabled state
12820
- disabledState = merge(normalState, {
12821
- style: {
12822
- color: "#cccccc" /* Palette.neutralColor20 */
12823
- }
12824
- }, AST.filterUserAttributes(disabledState || states.disabled || {}));
12825
- disabledStyle = disabledState.style;
12826
- delete disabledState.style;
12939
+ ['hover', 'select', 'disabled'].forEach((stateName, i) => {
12940
+ stateAttribs.push(merge(stateAttribs[0], AST.filterUserAttributes(args[i + 5] || states[stateName] || {})));
12941
+ stateStyles.push(stateAttribs[i + 1].style);
12942
+ delete stateAttribs[i + 1].style;
12943
+ });
12827
12944
  }
12828
12945
  // Add the events. IE9 and IE10 need mouseover and mouseout to function
12829
12946
  // (#667).
@@ -12837,7 +12954,7 @@
12837
12954
  label.setState(curState);
12838
12955
  }
12839
12956
  });
12840
- label.setState = function (state) {
12957
+ label.setState = (state = 0) => {
12841
12958
  // Hover state is temporary, don't record it
12842
12959
  if (state !== 1) {
12843
12960
  label.state = curState = state;
@@ -12846,31 +12963,19 @@
12846
12963
  label
12847
12964
  .removeClass(/highcharts-button-(normal|hover|pressed|disabled)/)
12848
12965
  .addClass('highcharts-button-' +
12849
- ['normal', 'hover', 'pressed', 'disabled'][state || 0]);
12966
+ ['normal', 'hover', 'pressed', 'disabled'][state]);
12850
12967
  if (!styledMode) {
12851
- label
12852
- .attr([
12853
- normalState,
12854
- hoverState,
12855
- selectState,
12856
- disabledState
12857
- ][state || 0]);
12858
- const css = [
12859
- normalStyle,
12860
- hoverStyle,
12861
- selectStyle,
12862
- disabledStyle
12863
- ][state || 0];
12968
+ label.attr(stateAttribs[state]);
12969
+ const css = stateStyles[state];
12864
12970
  if (isObject(css)) {
12865
12971
  label.css(css);
12866
12972
  }
12867
12973
  }
12868
12974
  };
12975
+ label.attr(stateAttribs[0]);
12869
12976
  // Presentational attributes
12870
12977
  if (!styledMode) {
12871
- label
12872
- .attr(normalState)
12873
- .css(extend({ cursor: 'default' }, normalStyle));
12978
+ label.css(extend({ cursor: 'default' }, normalStyle));
12874
12979
  // HTML labels don't need to handle pointer events because click and
12875
12980
  // mouseenter/mouseleave is bound to the underlying <g> element.
12876
12981
  // Should this be reconsidered, we need more complex logic to share
@@ -12900,26 +13005,17 @@
12900
13005
  * @param {number} width
12901
13006
  * The width of the line.
12902
13007
  *
12903
- * @param {string} [roundingFunction=round]
12904
- * The rounding function name on the `Math` object, can be one of
12905
- * `round`, `floor` or `ceil`.
12906
- *
12907
13008
  * @return {Highcharts.SVGPathArray}
12908
13009
  * The original points array, but modified to render crisply.
12909
13010
  */
12910
- crispLine(points, width, roundingFunction = 'round') {
12911
- const start = points[0];
12912
- const end = points[1];
13011
+ crispLine(points, width) {
13012
+ const [start, end] = points;
12913
13013
  // Normalize to a crisp line
12914
13014
  if (defined(start[1]) && start[1] === end[1]) {
12915
- // Subtract due to #1129. Now bottom and left axis gridlines behave
12916
- // the same.
12917
- start[1] = end[1] =
12918
- Math[roundingFunction](start[1]) - (width % 2 / 2);
13015
+ start[1] = end[1] = crisp(start[1], width);
12919
13016
  }
12920
13017
  if (defined(start[2]) && start[2] === end[2]) {
12921
- start[2] = end[2] =
12922
- Math[roundingFunction](start[2]) + (width % 2 / 2);
13018
+ start[2] = end[2] = crisp(start[2], width);
12923
13019
  }
12924
13020
  return points;
12925
13021
  }
@@ -13318,7 +13414,7 @@
13318
13414
  if (symbolFn) {
13319
13415
  // Check if there's a path defined for this symbol
13320
13416
  if (typeof x === 'number') {
13321
- path = symbolFn.call(this.symbols, Math.round(x || 0), Math.round(y || 0), width || 0, height || 0, options);
13417
+ path = symbolFn.call(this.symbols, x || 0, y || 0, width || 0, height || 0, options);
13322
13418
  }
13323
13419
  obj = this.path(path);
13324
13420
  if (!ren.styledMode) {
@@ -15477,11 +15573,12 @@
15477
15573
  overflow: 'justify',
15478
15574
  /**
15479
15575
  * The pixel padding for axis labels, to ensure white space between
15480
- * them.
15576
+ * them. Defaults to 4 for horizontal axes, 1 for vertical.
15481
15577
  *
15578
+ * @default undefined
15482
15579
  * @product highcharts gantt
15580
+ * @apioption xAxis.labels.padding
15483
15581
  */
15484
- padding: 5,
15485
15582
  /**
15486
15583
  * Whether to reserve space for the labels. By default, space is
15487
15584
  * reserved for the labels in these cases:
@@ -17792,7 +17889,7 @@
17792
17889
  });
17793
17890
  if (label.getBBox().width <
17794
17891
  axis.getSlotWidth(tick) - 2 *
17795
- labelOptions.padding) {
17892
+ (labelOptions.padding || 0)) {
17796
17893
  return;
17797
17894
  }
17798
17895
  }
@@ -17981,7 +18078,7 @@
17981
18078
  * Extendible method to return the path of the marker
17982
18079
  * @private
17983
18080
  */
17984
- getMarkPath(x, y, tickLength, tickWidth, horiz, renderer) {
18081
+ getMarkPath(x, y, tickLength, tickWidth, horiz = false, renderer) {
17985
18082
  return renderer.crispLine([[
17986
18083
  'M',
17987
18084
  x,
@@ -18109,9 +18206,7 @@
18109
18206
  * @param {number} [opacity]
18110
18207
  */
18111
18208
  render(index, old, opacity) {
18112
- const tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, axisStart = axis.pos, axisEnd = axisStart + axis.len, reverseCrisp = ((horiz && x === axisEnd) ||
18113
- (!horiz && y === axisStart)) ? -1 : 1, // #1480, #1687
18114
- pxPos = horiz ? x : y;
18209
+ const tick = this, axis = tick.axis, horiz = axis.horiz, pos = tick.pos, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), xy = tick.getPosition(horiz, pos, tickmarkOffset, old), x = xy.x, y = xy.y, axisStart = axis.pos, axisEnd = axisStart + axis.len, pxPos = horiz ? x : y;
18115
18210
  // Anything that is not between `axis.pos` and `axis.pos + axis.length`
18116
18211
  // should not be visible (#20166). The `correctFloat` is for reversed
18117
18212
  // axes in Safari.
@@ -18125,9 +18220,9 @@
18125
18220
  opacity = pick(opacity, 1);
18126
18221
  this.isActive = true;
18127
18222
  // Create the grid line
18128
- this.renderGridLine(old, opacity, reverseCrisp);
18223
+ this.renderGridLine(old, opacity);
18129
18224
  // Create the tick mark
18130
- this.renderMark(xy, opacity, reverseCrisp);
18225
+ this.renderMark(xy, opacity);
18131
18226
  // The label is created on init - now move it into place
18132
18227
  this.renderLabel(xy, old, labelOpacity, index);
18133
18228
  tick.isNew = false;
@@ -18140,9 +18235,8 @@
18140
18235
  * @function Highcharts.Tick#renderGridLine
18141
18236
  * @param {boolean} old Whether or not the tick is old
18142
18237
  * @param {number} opacity The opacity of the grid line
18143
- * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1
18144
18238
  */
18145
- renderGridLine(old, opacity, reverseCrisp) {
18239
+ renderGridLine(old, opacity) {
18146
18240
  const tick = this, axis = tick.axis, options = axis.options, attribs = {}, pos = tick.pos, type = tick.type, tickmarkOffset = pick(tick.tickmarkOffset, axis.tickmarkOffset), renderer = axis.chart.renderer;
18147
18241
  let gridLine = tick.gridLine, gridLinePath, gridLineWidth = options.gridLineWidth, gridLineColor = options.gridLineColor, dashStyle = options.gridLineDashStyle;
18148
18242
  if (tick.type === 'minor') {
@@ -18175,7 +18269,7 @@
18175
18269
  if (gridLine) {
18176
18270
  gridLinePath = axis.getPlotLinePath({
18177
18271
  value: pos + tickmarkOffset,
18178
- lineWidth: gridLine.strokeWidth() * reverseCrisp,
18272
+ lineWidth: gridLine.strokeWidth(),
18179
18273
  force: 'pass',
18180
18274
  old: old,
18181
18275
  acrossPanes: false // #18025
@@ -18197,9 +18291,8 @@
18197
18291
  * @function Highcharts.Tick#renderMark
18198
18292
  * @param {Highcharts.PositionObject} xy The position vector of the mark
18199
18293
  * @param {number} opacity The opacity of the mark
18200
- * @param {number} reverseCrisp Modifier for avoiding overlapping 1 or -1
18201
18294
  */
18202
- renderMark(xy, opacity, reverseCrisp) {
18295
+ renderMark(xy, opacity) {
18203
18296
  const tick = this, axis = tick.axis, options = axis.options, renderer = axis.chart.renderer, type = tick.type, tickSize = axis.tickSize(type ? type + 'Tick' : 'tick'), x = xy.x, y = xy.y, tickWidth = pick(options[type !== 'minor' ? 'tickWidth' : 'minorTickWidth'], !type && axis.isXAxis ? 1 : 0), // X axis defaults to 1
18204
18297
  tickColor = options[type !== 'minor' ? 'tickColor' : 'minorTickColor'];
18205
18298
  let mark = tick.mark;
@@ -18227,7 +18320,7 @@
18227
18320
  }
18228
18321
  }
18229
18322
  mark[isNewMark ? 'attr' : 'animate']({
18230
- d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth() * reverseCrisp, axis.horiz, renderer),
18323
+ d: tick.getMarkPath(x, y, tickSize[0], mark.strokeWidth(), axis.horiz, renderer),
18231
18324
  opacity: opacity
18232
18325
  });
18233
18326
  }
@@ -18567,7 +18660,7 @@
18567
18660
  * @name Highcharts.Axis#len
18568
18661
  * @type {number}
18569
18662
  */
18570
- axis.len = 0;
18663
+ axis.len ?? (axis.len = 0);
18571
18664
  axis.minRange = axis.userMinRange = options.minRange || options.maxZoom;
18572
18665
  axis.range = options.range;
18573
18666
  axis.offset = options.offset || 0;
@@ -18645,13 +18738,17 @@
18645
18738
  // Top and bottom axis defaults
18646
18739
  {
18647
18740
  labels: {
18648
- autoRotation: [-45]
18741
+ autoRotation: [-45],
18742
+ padding: 4
18649
18743
  },
18650
18744
  margin: 15
18651
18745
  } :
18652
18746
  // Left and right axis, title rotated 90 or 270 degrees
18653
18747
  // respectively
18654
18748
  {
18749
+ labels: {
18750
+ padding: 1
18751
+ },
18655
18752
  title: {
18656
18753
  rotation: 90 * this.side
18657
18754
  }
@@ -18861,10 +18958,13 @@
18861
18958
  val = axis.val2lin(val);
18862
18959
  }
18863
18960
  const value = sign * (val - localMin) * localA;
18864
- returnValue = (!axis.isRadial ? correctFloat(value) : value) +
18961
+ returnValue = value +
18865
18962
  cvsOffset +
18866
18963
  (sign * minPixelPadding) +
18867
18964
  (isNumber(pointPlacement) ? localA * pointPlacement : 0);
18965
+ if (!axis.isRadial) {
18966
+ returnValue = correctFloat(returnValue);
18967
+ }
18868
18968
  }
18869
18969
  return returnValue;
18870
18970
  }
@@ -18952,8 +19052,8 @@
18952
19052
  // Keep the translated value within sane bounds, and avoid Infinity
18953
19053
  // to fail the isNumber test (#7709).
18954
19054
  translatedValue = clamp(translatedValue, -1e5, 1e5);
18955
- x1 = x2 = Math.round(translatedValue + transB);
18956
- y1 = y2 = Math.round(cHeight - translatedValue - transB);
19055
+ x1 = x2 = translatedValue + transB;
19056
+ y1 = y2 = cHeight - translatedValue - transB;
18957
19057
  if (!isNumber(translatedValue)) { // No min or max
18958
19058
  skip = true;
18959
19059
  force = false; // #7175, don't force it when path is invalid
@@ -20284,17 +20384,17 @@
20284
20384
  * @function Highcharts.Axis#unsquish
20285
20385
  */
20286
20386
  unsquish() {
20287
- const labelOptions = this.options.labels, horiz = this.horiz, tickInterval = this.tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) +
20387
+ const labelOptions = this.options.labels, padding = labelOptions.padding || 0, horiz = this.horiz, tickInterval = this.tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) +
20288
20388
  this.max -
20289
20389
  this.min) /
20290
20390
  tickInterval), rotationOption = labelOptions.rotation,
20291
20391
  // We don't know the actual rendered line height at this point, but
20292
- // it defaults to 0.75em
20293
- lineHeight = this.labelMetrics().h, range = Math.max(this.max - this.min, 0),
20392
+ // it defaults to 0.8em
20393
+ lineHeight = correctFloat(this.labelMetrics().h * 0.8), range = Math.max(this.max - this.min, 0),
20294
20394
  // Return the multiple of tickInterval that is needed to avoid
20295
20395
  // collision
20296
20396
  getStep = function (spaceNeeded) {
20297
- let step = spaceNeeded / (slotSize || 1);
20397
+ let step = (spaceNeeded + 2 * padding) / (slotSize || 1);
20298
20398
  step = step > 1 ? Math.ceil(step) : 1;
20299
20399
  // Guard for very small or negative angles (#9835)
20300
20400
  if (step * tickInterval > range &&
@@ -20390,7 +20490,10 @@
20390
20490
  * @function Highcharts.Axis#renderUnsquish
20391
20491
  */
20392
20492
  renderUnsquish() {
20393
- const chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = labelOptions.style, horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - 2 * labelOptions.padding)), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = labelStyleOptions.textOverflow;
20493
+ const chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = labelOptions.style, horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - (horiz ?
20494
+ 2 * (labelOptions.padding || 0) :
20495
+ labelOptions.distance || 0 // #21172
20496
+ ))), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = labelStyleOptions.textOverflow;
20394
20497
  let commonWidth, commonTextOverflow, maxLabelLength = 0, label, i, pos;
20395
20498
  // Set rotation option unless it is "auto", like in gauges
20396
20499
  if (!isString(labelOptions.rotation)) {
@@ -20707,7 +20810,7 @@
20707
20810
  }
20708
20811
  // Due to GridAxis.tickSize, tickSize should be calculated after ticks
20709
20812
  // has rendered.
20710
- if (coll !== 'colorAxis') {
20813
+ if (coll !== 'colorAxis' && clipOffset) {
20711
20814
  const tickSize = this.tickSize('tick');
20712
20815
  axisOffset[side] = Math.max(axisOffset[side], (axis.axisTitleMargin || 0) + titleOffset +
20713
20816
  directionFactor * axis.offset, labelOffsetPadded, // #3027
@@ -20719,10 +20822,9 @@
20719
20822
  // the plot area and axis lines
20720
20823
  const clip = !axis.axisLine || options.offset ?
20721
20824
  0 :
20722
- // #4308, #4371:
20723
- Math.floor(axis.axisLine.strokeWidth() / 2) * 2;
20724
- clipOffset[invertedSide] =
20725
- Math.max(clipOffset[invertedSide], clip);
20825
+ // #4308, #4371
20826
+ axis.axisLine.strokeWidth() / 2;
20827
+ clipOffset[invertedSide] = Math.max(clipOffset[invertedSide], clip);
20726
20828
  }
20727
20829
  fireEvent(this, 'afterGetOffset');
20728
20830
  }
@@ -21357,6 +21459,7 @@
21357
21459
  'coll',
21358
21460
  'extKey',
21359
21461
  'hcEvents',
21462
+ 'len',
21360
21463
  'names',
21361
21464
  'series',
21362
21465
  'userMax',
@@ -22577,6 +22680,16 @@
22577
22680
  * @type {Highcharts.ColorString}
22578
22681
  * @apioption xAxis.plotBands.borderColor
22579
22682
  */
22683
+ /**
22684
+ * Border radius for the plot band. Applies only to gauges. Can be a pixel
22685
+ * value or a percentage, for example `50%`.
22686
+ *
22687
+ * @type {number|string}
22688
+ * @since 11.4.2
22689
+ * @sample {highcharts} highcharts/xaxis/plotbands-gauge-borderradius
22690
+ * Angular gauge with rounded plot bands
22691
+ * @apioption xAxis.plotBands.borderRadius
22692
+ */
22580
22693
  /**
22581
22694
  * Border width for the plot band. Also requires `borderColor` to be set.
22582
22695
  *
@@ -23134,7 +23247,7 @@
23134
23247
 
23135
23248
  return PlotLineOrBand;
23136
23249
  });
23137
- _registerModule(_modules, 'Core/Tooltip.js', [_modules['Core/Templating.js'], _modules['Core/Globals.js'], _modules['Core/Renderer/RendererUtilities.js'], _modules['Core/Renderer/RendererRegistry.js'], _modules['Core/Utilities.js']], function (F, H, R, RendererRegistry, U) {
23250
+ _registerModule(_modules, 'Core/Tooltip.js', [_modules['Core/Animation/AnimationUtilities.js'], _modules['Core/Templating.js'], _modules['Core/Globals.js'], _modules['Core/Renderer/RendererUtilities.js'], _modules['Core/Renderer/RendererRegistry.js'], _modules['Core/Utilities.js']], function (A, F, H, R, RendererRegistry, U) {
23138
23251
  /* *
23139
23252
  *
23140
23253
  * (c) 2010-2024 Torstein Honsi
@@ -23144,6 +23257,7 @@
23144
23257
  * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
23145
23258
  *
23146
23259
  * */
23260
+ const { animObject } = A;
23147
23261
  const { format } = F;
23148
23262
  const { composed, doc, isSafari } = H;
23149
23263
  const { distribute } = R;
@@ -23183,7 +23297,6 @@
23183
23297
  this.distance = 0;
23184
23298
  this.isHidden = true;
23185
23299
  this.isSticky = false;
23186
- this.now = {};
23187
23300
  this.options = {};
23188
23301
  this.outside = false;
23189
23302
  this.chart = chart;
@@ -23277,7 +23390,6 @@
23277
23390
  discardElement(this.container);
23278
23391
  }
23279
23392
  U.clearTimeout(this.hideTimer);
23280
- U.clearTimeout(this.tooltipTimeout);
23281
23393
  }
23282
23394
  /**
23283
23395
  * Extendable method to get the anchor position of the tooltip
@@ -23438,19 +23550,15 @@
23438
23550
  // container.
23439
23551
  if (tooltip.outside) {
23440
23552
  const label = this.label;
23441
- const { xSetter, ySetter } = label;
23442
- label.xSetter = function (value) {
23443
- xSetter.call(label, tooltip.distance);
23444
- if (container) {
23445
- container.style.left = value + 'px';
23446
- }
23447
- };
23448
- label.ySetter = function (value) {
23449
- ySetter.call(label, tooltip.distance);
23450
- if (container) {
23451
- container.style.top = value + 'px';
23452
- }
23453
- };
23553
+ [label.xSetter, label.ySetter].forEach((setter, i) => {
23554
+ label[i ? 'ySetter' : 'xSetter'] = (value) => {
23555
+ setter.call(label, tooltip.distance);
23556
+ label[i ? 'y' : 'x'] = value;
23557
+ if (container) {
23558
+ container.style[i ? 'top' : 'left'] = `${value}px`;
23559
+ }
23560
+ };
23561
+ });
23454
23562
  }
23455
23563
  this.label
23456
23564
  .attr({ zIndex: 8 })
@@ -23701,15 +23809,6 @@
23701
23809
  * @type {Array<null>}
23702
23810
  */
23703
23811
  this.crosshairs = [];
23704
- /**
23705
- * Current values of x and y when animating.
23706
- *
23707
- * @private
23708
- * @readonly
23709
- * @name Highcharts.Tooltip#now
23710
- * @type {Highcharts.PositionObject}
23711
- */
23712
- this.now = { x: 0, y: 0 };
23713
23812
  /**
23714
23813
  * Tooltips are initially hidden.
23715
23814
  *
@@ -23773,38 +23872,13 @@
23773
23872
  * @param {number} anchorY
23774
23873
  */
23775
23874
  move(x, y, anchorX, anchorY) {
23776
- const tooltip = this, now = tooltip.now, animate = tooltip.options.animation !== false &&
23777
- !tooltip.isHidden &&
23778
- // When we get close to the target position, abort animation and
23779
- // land on the right place (#3056)
23780
- (Math.abs(x - now.x) > 1 || Math.abs(y - now.y) > 1), skipAnchor = tooltip.followPointer || tooltip.len > 1;
23781
- // Get intermediate values for animation
23782
- extend(now, {
23783
- x: animate ? (2 * now.x + x) / 3 : x,
23784
- y: animate ? (now.y + y) / 2 : y,
23785
- anchorX: skipAnchor ?
23786
- void 0 :
23787
- animate ? (2 * now.anchorX + anchorX) / 3 : anchorX,
23788
- anchorY: skipAnchor ?
23789
- void 0 :
23790
- animate ? (now.anchorY + anchorY) / 2 : anchorY
23791
- });
23792
- // Move to the intermediate value
23793
- tooltip.getLabel().attr(now);
23794
- tooltip.drawTracker();
23795
- // Run on next tick of the mouse tracker
23796
- if (animate) {
23797
- // Never allow two timeouts
23798
- U.clearTimeout(this.tooltipTimeout);
23799
- // Set the fixed interval ticking for the smooth tooltip
23800
- this.tooltipTimeout = setTimeout(function () {
23801
- // The interval function may still be running during destroy,
23802
- // so check that the chart is really there before calling.
23803
- if (tooltip) {
23804
- tooltip.move(x, y, anchorX, anchorY);
23805
- }
23806
- }, 32);
23875
+ const tooltip = this, animation = animObject(!tooltip.isHidden && tooltip.options.animation), skipAnchor = tooltip.followPointer || (tooltip.len || 0) > 1, attr = { x, y };
23876
+ if (!skipAnchor) {
23877
+ attr.anchorX = anchorX;
23878
+ attr.anchorY = anchorY;
23807
23879
  }
23880
+ animation.step = () => tooltip.drawTracker();
23881
+ tooltip.getLabel().animate(attr, animation);
23808
23882
  }
23809
23883
  /**
23810
23884
  * Refresh the tooltip's text and position.
@@ -24527,7 +24601,7 @@
24527
24601
  const { animObject } = A;
24528
24602
  const { defaultOptions } = D;
24529
24603
  const { format } = F;
24530
- const { addEvent, erase, extend, fireEvent, getNestedProperty, isArray, isFunction, isNumber, isObject, merge, pick, syncTimeout, removeEvent, uniqueKey } = U;
24604
+ const { addEvent, crisp, erase, extend, fireEvent, getNestedProperty, isArray, isFunction, isNumber, isObject, merge, pick, syncTimeout, removeEvent, uniqueKey } = U;
24531
24605
  /* eslint-disable no-invalid-this, valid-jsdoc */
24532
24606
  /* *
24533
24607
  *
@@ -25635,7 +25709,8 @@
25635
25709
  }, AST.filterUserAttributes(haloOptions.attributes || {})));
25636
25710
  }
25637
25711
  }
25638
- else if (halo && halo.point && halo.point.haloPath) {
25712
+ else if (halo?.point?.haloPath &&
25713
+ !halo.point.destroyed) {
25639
25714
  // Animate back to 0 on the current halo point (#6055)
25640
25715
  halo.animate({ d: halo.point.haloPath(0) }, null,
25641
25716
  // Hide after unhovering. The `complete` callback runs in the
@@ -25658,7 +25733,7 @@
25658
25733
  */
25659
25734
  haloPath(size) {
25660
25735
  const pos = this.pos();
25661
- return pos ? this.series.chart.renderer.symbols.circle(Math.floor(pos[0]) - size, pos[1] - size, size * 2, size * 2) : [];
25736
+ return pos ? this.series.chart.renderer.symbols.circle(crisp(pos[0], 1) - size, pos[1] - size, size * 2, size * 2) : [];
25662
25737
  }
25663
25738
  }
25664
25739
  /* *
@@ -30357,6 +30432,21 @@
30357
30432
  * @type {Highcharts.AlignValue|null}
30358
30433
  */
30359
30434
  align: 'center',
30435
+ /**
30436
+ * Alignment method for data labels. If set to `plotEdges`, the labels
30437
+ * are aligned within the plot area in the direction of the y-axis. So
30438
+ * in a regular column chart, the labels are aligned vertically
30439
+ * according to the `verticalAlign` setting. In a bar chart, which is
30440
+ * inverted, the labels are aligned horizontally according to the
30441
+ * `align` setting. Applies to cartesian series only.
30442
+ *
30443
+ * @sample {highcharts} highcharts/series-bar/datalabels-alignto/
30444
+ * Align to plot edges
30445
+ *
30446
+ * @type {string}
30447
+ * @since 11.4.2
30448
+ * @apioption plotOptions.series.dataLabels.alignTo
30449
+ */
30360
30450
  /**
30361
30451
  * Whether to allow data labels to overlap. To make the labels less
30362
30452
  * sensitive for overlapping, the
@@ -31414,7 +31504,7 @@
31414
31504
  const { registerEventOptions } = F;
31415
31505
  const { svg, win } = H;
31416
31506
  const { seriesTypes } = SeriesRegistry;
31417
- const { arrayMax, arrayMin, clamp, correctFloat, defined, destroyObjectProperties, diffObjects, erase, error, extend, find, fireEvent, getClosestDistance, getNestedProperty, insertItem, isArray, isNumber, isString, merge, objectEach, pick, removeEvent, splat, syncTimeout } = U;
31507
+ const { arrayMax, arrayMin, clamp, correctFloat, crisp, defined, destroyObjectProperties, diffObjects, erase, error, extend, find, fireEvent, getClosestDistance, getNestedProperty, insertItem, isArray, isNumber, isString, merge, objectEach, pick, removeEvent, splat, syncTimeout } = U;
31418
31508
  /* *
31419
31509
  *
31420
31510
  * Class
@@ -32378,10 +32468,7 @@
32378
32468
  * Force getting extremes of a total series data range.
32379
32469
  */
32380
32470
  getProcessedData(forceExtremesFromAll) {
32381
- const series = this, xAxis = series.xAxis, options = series.options, cropThreshold = options.cropThreshold, getExtremesFromAll = forceExtremesFromAll ||
32382
- series.getExtremesFromAll ||
32383
- options.getExtremesFromAll, // #4599
32384
- logarithmic = xAxis?.logarithmic, isCartesian = series.isCartesian;
32471
+ const series = this, xAxis = series.xAxis, options = series.options, cropThreshold = options.cropThreshold, logarithmic = xAxis?.logarithmic, isCartesian = series.isCartesian;
32385
32472
  let croppedData, cropped, cropStart = 0, xExtremes, min, max,
32386
32473
  // Copied during slice operation:
32387
32474
  processedXData = series.xData, processedYData = series.yData, updatingNames = false;
@@ -32396,7 +32483,7 @@
32396
32483
  // Optionally filter out points outside the plot area
32397
32484
  if (isCartesian &&
32398
32485
  series.sorted &&
32399
- !getExtremesFromAll &&
32486
+ !forceExtremesFromAll &&
32400
32487
  (!cropThreshold ||
32401
32488
  dataLength > cropThreshold ||
32402
32489
  series.forceCrop)) {
@@ -32637,16 +32724,24 @@
32637
32724
  * Force getting extremes of a total series data range.
32638
32725
  */
32639
32726
  getExtremes(yData, forceExtremesFromAll) {
32640
- const xAxis = this.xAxis, yAxis = this.yAxis, xData = this.processedXData || this.xData, activeYData = [],
32727
+ const xAxis = this.xAxis, yAxis = this.yAxis, activeYData = [],
32641
32728
  // Handle X outside the viewed area. This does not work with
32642
32729
  // non-sorted data like scatter (#7639).
32643
32730
  shoulder = this.requireSorting && !this.is('column') ?
32644
32731
  1 : 0,
32645
32732
  // #2117, need to compensate for log X axis
32646
- positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false;
32647
- let xExtremes, validValue, withinRange, x, y, i, j, xMin = 0, xMax = 0, activeCounter = 0;
32648
- yData = yData || this.stackedYData || this.processedYData || [];
32649
- const yDataLength = yData.length;
32733
+ positiveValuesOnly = yAxis ? yAxis.positiveValuesOnly : false, getExtremesFromAll = forceExtremesFromAll ||
32734
+ this.getExtremesFromAll ||
32735
+ this.options.getExtremesFromAll; // #4599
32736
+ let { processedXData, processedYData } = this, xExtremes, validValue, withinRange, x, y, i, j, xMin = 0, xMax = 0, activeCounter = 0;
32737
+ // Get the processed data from the full range (#21003)
32738
+ if (this.cropped && getExtremesFromAll) {
32739
+ const processedData = this.getProcessedData(true);
32740
+ processedXData = processedData.xData;
32741
+ processedYData = processedData.yData;
32742
+ }
32743
+ yData = yData || this.stackedYData || processedYData || [];
32744
+ const yDataLength = yData.length, xData = processedXData || this.xData;
32650
32745
  if (xAxis) {
32651
32746
  xExtremes = xAxis.getExtremes();
32652
32747
  xMin = xExtremes.min;
@@ -33216,12 +33311,16 @@
33216
33311
  }
33217
33312
  const pos = point.pos();
33218
33313
  if (isNumber(radius) && pos) {
33219
- attribs.x = pos[0] - radius;
33220
- attribs.y = pos[1] - radius;
33221
33314
  if (seriesOptions.crisp) {
33222
- // Math.floor for #1843:
33223
- attribs.x = Math.floor(attribs.x);
33315
+ pos[0] = crisp(pos[0], point.hasImage ?
33316
+ 0 :
33317
+ symbol === 'rect' ?
33318
+ // Rectangle symbols need crisp edges, others don't
33319
+ seriesMarkerOptions?.lineWidth || 0 :
33320
+ 1);
33224
33321
  }
33322
+ attribs.x = pos[0] - radius;
33323
+ attribs.y = pos[1] - radius;
33225
33324
  }
33226
33325
  if (radius) {
33227
33326
  attribs.width = attribs.height = 2 * radius;
@@ -36393,7 +36492,7 @@
36393
36492
  * @emits Highcharts.Chart#event:afterSetChartSize
36394
36493
  */
36395
36494
  setChartSize(skipAxes) {
36396
- const chart = this, inverted = chart.inverted, renderer = chart.renderer, chartWidth = chart.chartWidth, chartHeight = chart.chartHeight, optionsChart = chart.options.chart, spacing = chart.spacing, clipOffset = chart.clipOffset;
36495
+ const chart = this, { chartHeight, chartWidth, inverted, spacing, renderer } = chart, clipOffset = chart.clipOffset, clipRoundFunc = Math[inverted ? 'floor' : 'round'];
36397
36496
  let plotLeft, plotTop, plotWidth, plotHeight;
36398
36497
  /**
36399
36498
  * The current left position of the plot area in pixels.
@@ -36425,7 +36524,6 @@
36425
36524
  chart.plotHeight = plotHeight = Math.max(0, Math.round(chartHeight - plotTop - chart.marginBottom));
36426
36525
  chart.plotSizeX = inverted ? plotHeight : plotWidth;
36427
36526
  chart.plotSizeY = inverted ? plotWidth : plotHeight;
36428
- chart.plotBorderWidth = optionsChart.plotBorderWidth || 0;
36429
36527
  // Set boxes used for alignment
36430
36528
  chart.spacingBox = renderer.spacingBox = {
36431
36529
  x: spacing[3],
@@ -36439,17 +36537,15 @@
36439
36537
  width: plotWidth,
36440
36538
  height: plotHeight
36441
36539
  };
36442
- const plotBorderWidth = 2 * Math.floor(chart.plotBorderWidth / 2), clipX = Math.ceil(Math.max(plotBorderWidth, clipOffset[3]) / 2), clipY = Math.ceil(Math.max(plotBorderWidth, clipOffset[0]) / 2);
36443
- chart.clipBox = {
36444
- x: clipX,
36445
- y: clipY,
36446
- width: Math.floor(chart.plotSizeX -
36447
- Math.max(plotBorderWidth, clipOffset[1]) / 2 -
36448
- clipX),
36449
- height: Math.max(0, Math.floor(chart.plotSizeY -
36450
- Math.max(plotBorderWidth, clipOffset[2]) / 2 -
36451
- clipY))
36452
- };
36540
+ // Compute the clipping box
36541
+ if (clipOffset) {
36542
+ chart.clipBox = {
36543
+ x: clipRoundFunc(clipOffset[3]),
36544
+ y: clipRoundFunc(clipOffset[0]),
36545
+ width: clipRoundFunc(chart.plotSizeX - clipOffset[1] - clipOffset[3]),
36546
+ height: clipRoundFunc(chart.plotSizeY - clipOffset[0] - clipOffset[2])
36547
+ };
36548
+ }
36453
36549
  if (!skipAxes) {
36454
36550
  chart.axes.forEach(function (axis) {
36455
36551
  axis.setAxisSize();
@@ -36467,7 +36563,7 @@
36467
36563
  */
36468
36564
  resetMargins() {
36469
36565
  fireEvent(this, 'resetMargins');
36470
- const chart = this, chartOptions = chart.options.chart;
36566
+ const chart = this, chartOptions = chart.options.chart, plotBorderWidth = chartOptions.plotBorderWidth || 0, halfWidth = plotBorderWidth / 2;
36471
36567
  // Create margin and spacing array
36472
36568
  ['margin', 'spacing'].forEach(function splashArrays(target) {
36473
36569
  const value = chartOptions[target], values = isObject(value) ? value : [value, value, value, value];
@@ -36486,7 +36582,13 @@
36486
36582
  chart[m] = pick(chart.margin[side], chart.spacing[side]);
36487
36583
  });
36488
36584
  chart.axisOffset = [0, 0, 0, 0]; // Top, right, bottom, left
36489
- chart.clipOffset = [0, 0, 0, 0];
36585
+ chart.clipOffset = [
36586
+ halfWidth,
36587
+ halfWidth,
36588
+ halfWidth,
36589
+ halfWidth
36590
+ ];
36591
+ chart.plotBorderWidth = plotBorderWidth;
36490
36592
  }
36491
36593
  /**
36492
36594
  * Internal function to draw or redraw the borders and backgrounds for chart
@@ -36729,7 +36831,8 @@
36729
36831
  chart.setChartSize();
36730
36832
  for (const axis of axes) {
36731
36833
  const { options } = axis, { labels } = options;
36732
- if (axis.horiz &&
36834
+ if (chart.hasCartesianSeries && // #20948
36835
+ axis.horiz &&
36733
36836
  axis.visible &&
36734
36837
  labels.enabled &&
36735
36838
  axis.series.length &&
@@ -37651,7 +37754,7 @@
37651
37754
  // Remove active points for shared tooltip
37652
37755
  this.hoverPoints?.forEach((point) => point.setState());
37653
37756
  for (const axis of axes) {
37654
- const { horiz, len, minPointOffset = 0, options, reversed } = axis, wh = horiz ? 'width' : 'height', xy = horiz ? 'x' : 'y', toLength = to[wh] || axis.len, fromLength = from[wh] || axis.len,
37757
+ const { horiz, len, minPointOffset = 0, options, reversed } = axis, wh = horiz ? 'width' : 'height', xy = horiz ? 'x' : 'y', toLength = pick(to[wh], axis.len), fromLength = pick(from[wh], axis.len),
37655
37758
  // If fingers pinched very close on this axis, treat as pan
37656
37759
  scale = Math.abs(toLength) < 10 ?
37657
37760
  1 :
@@ -38217,23 +38320,7 @@
38217
38320
  * @private
38218
38321
  */
38219
38322
  moveFixedElements() {
38220
- const { container, inverted, scrollablePixelsX, scrollablePixelsY } = this.chart, fixedRenderer = this.fixedRenderer, fixedSelectors = [
38221
- '.highcharts-breadcrumbs-group',
38222
- '.highcharts-contextbutton',
38223
- '.highcharts-caption',
38224
- '.highcharts-credits',
38225
- '.highcharts-legend',
38226
- '.highcharts-legend-checkbox',
38227
- '.highcharts-navigator-series',
38228
- '.highcharts-navigator-xaxis',
38229
- '.highcharts-navigator-yaxis',
38230
- '.highcharts-navigator',
38231
- '.highcharts-reset-zoom',
38232
- '.highcharts-drillup-button',
38233
- '.highcharts-scrollbar',
38234
- '.highcharts-subtitle',
38235
- '.highcharts-title'
38236
- ];
38323
+ const { container, inverted, scrollablePixelsX, scrollablePixelsY } = this.chart, fixedRenderer = this.fixedRenderer, fixedSelectors = ScrollablePlotArea.fixedSelectors;
38237
38324
  let axisClass;
38238
38325
  if (scrollablePixelsX && !inverted) {
38239
38326
  axisClass = '.highcharts-yaxis';
@@ -38260,6 +38347,24 @@
38260
38347
  }
38261
38348
  }
38262
38349
  }
38350
+ ScrollablePlotArea.fixedSelectors = [
38351
+ '.highcharts-breadcrumbs-group',
38352
+ '.highcharts-contextbutton',
38353
+ '.highcharts-caption',
38354
+ '.highcharts-credits',
38355
+ '.highcharts-drillup-button',
38356
+ '.highcharts-legend',
38357
+ '.highcharts-legend-checkbox',
38358
+ '.highcharts-navigator-series',
38359
+ '.highcharts-navigator-xaxis',
38360
+ '.highcharts-navigator-yaxis',
38361
+ '.highcharts-navigator',
38362
+ '.highcharts-range-selector-group',
38363
+ '.highcharts-reset-zoom',
38364
+ '.highcharts-scrollbar',
38365
+ '.highcharts-subtitle',
38366
+ '.highcharts-title'
38367
+ ];
38263
38368
  /* *
38264
38369
  *
38265
38370
  * Default Export
@@ -39553,7 +39658,248 @@
39553
39658
 
39554
39659
  return LineSeries;
39555
39660
  });
39556
- _registerModule(_modules, 'Series/Area/AreaSeries.js', [_modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (SeriesRegistry, U) {
39661
+ _registerModule(_modules, 'Series/Area/AreaSeriesDefaults.js', [], function () {
39662
+ /* *
39663
+ *
39664
+ * (c) 2010-2024 Torstein Honsi
39665
+ *
39666
+ * License: www.highcharts.com/license
39667
+ *
39668
+ * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
39669
+ *
39670
+ * */
39671
+ /* *
39672
+ *
39673
+ * API Options
39674
+ *
39675
+ * */
39676
+ /**
39677
+ * The area series type.
39678
+ *
39679
+ * @sample {highcharts} highcharts/demo/area-basic/
39680
+ * Area chart
39681
+ * @sample {highstock} stock/demo/area/
39682
+ * Area chart
39683
+ *
39684
+ * @extends plotOptions.line
39685
+ * @excluding useOhlcData
39686
+ * @product highcharts highstock
39687
+ * @optionparent plotOptions.area
39688
+ */
39689
+ const AreaSeriesDefaults = {
39690
+ /**
39691
+ * @see [fillColor](#plotOptions.area.fillColor)
39692
+ * @see [fillOpacity](#plotOptions.area.fillOpacity)
39693
+ *
39694
+ * @apioption plotOptions.area.color
39695
+ */
39696
+ /**
39697
+ * Fill color or gradient for the area. When `undefined`, the series'
39698
+ * `color` is used with the series' `fillOpacity`.
39699
+ *
39700
+ * In styled mode, the fill color can be set with the `.highcharts-area`
39701
+ * class name.
39702
+ *
39703
+ * @see [color](#plotOptions.area.color)
39704
+ * @see [fillOpacity](#plotOptions.area.fillOpacity)
39705
+ *
39706
+ * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/
39707
+ * Undefined by default
39708
+ * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/
39709
+ * Gradient
39710
+ *
39711
+ * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39712
+ * @product highcharts highstock
39713
+ * @apioption plotOptions.area.fillColor
39714
+ */
39715
+ /**
39716
+ * Fill opacity for the area. When you set an explicit `fillColor`,
39717
+ * the `fillOpacity` is not applied. Instead, you should define the
39718
+ * opacity in the `fillColor` with an rgba color definition. The
39719
+ * `fillOpacity` setting, also the default setting, overrides the alpha
39720
+ * component of the `color` setting.
39721
+ *
39722
+ * In styled mode, the fill opacity can be set with the
39723
+ * `.highcharts-area` class name.
39724
+ *
39725
+ * @see [color](#plotOptions.area.color)
39726
+ * @see [fillColor](#plotOptions.area.fillColor)
39727
+ *
39728
+ * @sample {highcharts} highcharts/plotoptions/area-fillopacity/
39729
+ * Automatic fill color and fill opacity of 0.1
39730
+ *
39731
+ * @type {number}
39732
+ * @default {highcharts} 0.75
39733
+ * @default {highstock} 0.75
39734
+ * @product highcharts highstock
39735
+ * @apioption plotOptions.area.fillOpacity
39736
+ */
39737
+ /**
39738
+ * A separate color for the graph line. By default the line takes the
39739
+ * `color` of the series, but the lineColor setting allows setting a
39740
+ * separate color for the line without altering the `fillColor`.
39741
+ *
39742
+ * In styled mode, the line stroke can be set with the
39743
+ * `.highcharts-graph` class name.
39744
+ *
39745
+ * @sample {highcharts} highcharts/plotoptions/area-linecolor/
39746
+ * Dark gray line
39747
+ *
39748
+ * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39749
+ * @product highcharts highstock
39750
+ * @apioption plotOptions.area.lineColor
39751
+ */
39752
+ /**
39753
+ * A separate color for the negative part of the area. Note that `zones`
39754
+ * takes precedence over the negative fill color.
39755
+ *
39756
+ * In styled mode, a negative color is set with the
39757
+ * `.highcharts-negative` class name.
39758
+ *
39759
+ * @see [negativeColor](#plotOptions.area.negativeColor)
39760
+ *
39761
+ * @sample {highcharts} highcharts/css/series-negative-color/
39762
+ * Negative color in styled mode
39763
+ *
39764
+ * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39765
+ * @since 3.0
39766
+ * @product highcharts
39767
+ * @apioption plotOptions.area.negativeFillColor
39768
+ */
39769
+ /**
39770
+ * Whether the whole area or just the line should respond to mouseover
39771
+ * tooltips and other mouse or touch events.
39772
+ *
39773
+ * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/
39774
+ * Display the tooltip when the area is hovered
39775
+ *
39776
+ * @type {boolean}
39777
+ * @default false
39778
+ * @since 1.1.6
39779
+ * @product highcharts highstock
39780
+ * @apioption plotOptions.area.trackByArea
39781
+ */
39782
+ /**
39783
+ * The Y axis value to serve as the base for the area, for
39784
+ * distinguishing between values above and below a threshold. The area
39785
+ * between the graph and the threshold is filled.
39786
+ *
39787
+ * * If a number is given, the Y axis will scale to the threshold.
39788
+ * * If `null`, the scaling behaves like a line series with fill between
39789
+ * the graph and the Y axis minimum.
39790
+ * * If `Infinity` or `-Infinity`, the area between the graph and the
39791
+ * corresponding Y axis extreme is filled (since v6.1.0).
39792
+ *
39793
+ * @sample {highcharts} highcharts/plotoptions/area-threshold/
39794
+ * A threshold of 100
39795
+ * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/
39796
+ * A threshold of Infinity
39797
+ *
39798
+ * @type {number|null}
39799
+ * @since 2.0
39800
+ * @product highcharts highstock
39801
+ */
39802
+ threshold: 0,
39803
+ legendSymbol: 'areaMarker'
39804
+ };
39805
+ /**
39806
+ * A `area` series. If the [type](#series.area.type) option is not
39807
+ * specified, it is inherited from [chart.type](#chart.type).
39808
+ *
39809
+ * @extends series,plotOptions.area
39810
+ * @excluding dataParser, dataURL, useOhlcData
39811
+ * @product highcharts highstock
39812
+ * @apioption series.area
39813
+ */
39814
+ /**
39815
+ * @see [fillColor](#series.area.fillColor)
39816
+ * @see [fillOpacity](#series.area.fillOpacity)
39817
+ *
39818
+ * @apioption series.area.color
39819
+ */
39820
+ /**
39821
+ * An array of data points for the series. For the `area` series type,
39822
+ * points can be given in the following ways:
39823
+ *
39824
+ * 1. An array of numerical values. In this case, the numerical values will be
39825
+ * interpreted as `y` options. The `x` values will be automatically
39826
+ * calculated, either starting at 0 and incremented by 1, or from
39827
+ * `pointStart` * and `pointInterval` given in the series options. If the
39828
+ * axis has categories, these will be used. Example:
39829
+ * ```js
39830
+ * data: [0, 5, 3, 5]
39831
+ * ```
39832
+ *
39833
+ * 2. An array of arrays with 2 values. In this case, the values correspond to
39834
+ * `x,y`. If the first value is a string, it is applied as the name of the
39835
+ * point, and the `x` value is inferred.
39836
+ * ```js
39837
+ * data: [
39838
+ * [0, 9],
39839
+ * [1, 7],
39840
+ * [2, 6]
39841
+ * ]
39842
+ * ```
39843
+ *
39844
+ * 3. An array of objects with named values. The following snippet shows only a
39845
+ * few settings, see the complete options set below. If the total number of
39846
+ * data points exceeds the series'
39847
+ * [turboThreshold](#series.area.turboThreshold), this option is not
39848
+ * available.
39849
+ * ```js
39850
+ * data: [{
39851
+ * x: 1,
39852
+ * y: 9,
39853
+ * name: "Point2",
39854
+ * color: "#00FF00"
39855
+ * }, {
39856
+ * x: 1,
39857
+ * y: 6,
39858
+ * name: "Point1",
39859
+ * color: "#FF00FF"
39860
+ * }]
39861
+ * ```
39862
+ *
39863
+ * @sample {highcharts} highcharts/chart/reflow-true/
39864
+ * Numerical values
39865
+ * @sample {highcharts} highcharts/series/data-array-of-arrays/
39866
+ * Arrays of numeric x and y
39867
+ * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
39868
+ * Arrays of datetime x and y
39869
+ * @sample {highcharts} highcharts/series/data-array-of-name-value/
39870
+ * Arrays of point.name and y
39871
+ * @sample {highcharts} highcharts/series/data-array-of-objects/
39872
+ * Config objects
39873
+ *
39874
+ * @type {Array<number|Array<(number|string),(number|null)>|null|*>}
39875
+ * @extends series.line.data
39876
+ * @product highcharts highstock
39877
+ * @apioption series.area.data
39878
+ */
39879
+ /**
39880
+ * @see [color](#series.area.color)
39881
+ * @see [fillOpacity](#series.area.fillOpacity)
39882
+ *
39883
+ * @apioption series.area.fillColor
39884
+ */
39885
+ /**
39886
+ * @see [color](#series.area.color)
39887
+ * @see [fillColor](#series.area.fillColor)
39888
+ *
39889
+ * @default {highcharts} 0.75
39890
+ * @default {highstock} 0.75
39891
+ * @apioption series.area.fillOpacity
39892
+ */
39893
+ ''; // Adds doclets above to transpiled
39894
+ /* *
39895
+ *
39896
+ * Default Export
39897
+ *
39898
+ * */
39899
+
39900
+ return AreaSeriesDefaults;
39901
+ });
39902
+ _registerModule(_modules, 'Series/Area/AreaSeries.js', [_modules['Series/Area/AreaSeriesDefaults.js'], _modules['Core/Series/SeriesRegistry.js'], _modules['Core/Utilities.js']], function (AreaSeriesDefaults, SeriesRegistry, U) {
39557
39903
  /* *
39558
39904
  *
39559
39905
  * (c) 2010-2024 Torstein Honsi
@@ -39866,134 +40212,7 @@
39866
40212
  * Static Properties
39867
40213
  *
39868
40214
  * */
39869
- /**
39870
- * The area series type.
39871
- *
39872
- * @sample {highcharts} highcharts/demo/area-basic/
39873
- * Area chart
39874
- * @sample {highstock} stock/demo/area/
39875
- * Area chart
39876
- *
39877
- * @extends plotOptions.line
39878
- * @excluding useOhlcData
39879
- * @product highcharts highstock
39880
- * @optionparent plotOptions.area
39881
- */
39882
- AreaSeries.defaultOptions = merge(LineSeries.defaultOptions, {
39883
- /**
39884
- * @see [fillColor](#plotOptions.area.fillColor)
39885
- * @see [fillOpacity](#plotOptions.area.fillOpacity)
39886
- *
39887
- * @apioption plotOptions.area.color
39888
- */
39889
- /**
39890
- * Fill color or gradient for the area. When `undefined`, the series'
39891
- * `color` is used with the series' `fillOpacity`.
39892
- *
39893
- * In styled mode, the fill color can be set with the `.highcharts-area`
39894
- * class name.
39895
- *
39896
- * @see [color](#plotOptions.area.color)
39897
- * @see [fillOpacity](#plotOptions.area.fillOpacity)
39898
- *
39899
- * @sample {highcharts} highcharts/plotoptions/area-fillcolor-default/
39900
- * Undefined by default
39901
- * @sample {highcharts} highcharts/plotoptions/area-fillcolor-gradient/
39902
- * Gradient
39903
- *
39904
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39905
- * @product highcharts highstock
39906
- * @apioption plotOptions.area.fillColor
39907
- */
39908
- /**
39909
- * Fill opacity for the area. When you set an explicit `fillColor`,
39910
- * the `fillOpacity` is not applied. Instead, you should define the
39911
- * opacity in the `fillColor` with an rgba color definition. The
39912
- * `fillOpacity` setting, also the default setting, overrides the alpha
39913
- * component of the `color` setting.
39914
- *
39915
- * In styled mode, the fill opacity can be set with the
39916
- * `.highcharts-area` class name.
39917
- *
39918
- * @see [color](#plotOptions.area.color)
39919
- * @see [fillColor](#plotOptions.area.fillColor)
39920
- *
39921
- * @sample {highcharts} highcharts/plotoptions/area-fillopacity/
39922
- * Automatic fill color and fill opacity of 0.1
39923
- *
39924
- * @type {number}
39925
- * @default {highcharts} 0.75
39926
- * @default {highstock} 0.75
39927
- * @product highcharts highstock
39928
- * @apioption plotOptions.area.fillOpacity
39929
- */
39930
- /**
39931
- * A separate color for the graph line. By default the line takes the
39932
- * `color` of the series, but the lineColor setting allows setting a
39933
- * separate color for the line without altering the `fillColor`.
39934
- *
39935
- * In styled mode, the line stroke can be set with the
39936
- * `.highcharts-graph` class name.
39937
- *
39938
- * @sample {highcharts} highcharts/plotoptions/area-linecolor/
39939
- * Dark gray line
39940
- *
39941
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39942
- * @product highcharts highstock
39943
- * @apioption plotOptions.area.lineColor
39944
- */
39945
- /**
39946
- * A separate color for the negative part of the area.
39947
- *
39948
- * In styled mode, a negative color is set with the
39949
- * `.highcharts-negative` class name.
39950
- *
39951
- * @see [negativeColor](#plotOptions.area.negativeColor)
39952
- *
39953
- * @sample {highcharts} highcharts/css/series-negative-color/
39954
- * Negative color in styled mode
39955
- *
39956
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
39957
- * @since 3.0
39958
- * @product highcharts
39959
- * @apioption plotOptions.area.negativeFillColor
39960
- */
39961
- /**
39962
- * Whether the whole area or just the line should respond to mouseover
39963
- * tooltips and other mouse or touch events.
39964
- *
39965
- * @sample {highcharts|highstock} highcharts/plotoptions/area-trackbyarea/
39966
- * Display the tooltip when the area is hovered
39967
- *
39968
- * @type {boolean}
39969
- * @default false
39970
- * @since 1.1.6
39971
- * @product highcharts highstock
39972
- * @apioption plotOptions.area.trackByArea
39973
- */
39974
- /**
39975
- * The Y axis value to serve as the base for the area, for
39976
- * distinguishing between values above and below a threshold. The area
39977
- * between the graph and the threshold is filled.
39978
- *
39979
- * * If a number is given, the Y axis will scale to the threshold.
39980
- * * If `null`, the scaling behaves like a line series with fill between
39981
- * the graph and the Y axis minimum.
39982
- * * If `Infinity` or `-Infinity`, the area between the graph and the
39983
- * corresponding Y axis extreme is filled (since v6.1.0).
39984
- *
39985
- * @sample {highcharts} highcharts/plotoptions/area-threshold/
39986
- * A threshold of 100
39987
- * @sample {highcharts} highcharts/plotoptions/area-threshold-infinity/
39988
- * A threshold of Infinity
39989
- *
39990
- * @type {number|null}
39991
- * @since 2.0
39992
- * @product highcharts highstock
39993
- */
39994
- threshold: 0,
39995
- legendSymbol: 'areaMarker'
39996
- });
40215
+ AreaSeries.defaultOptions = merge(LineSeries.defaultOptions, AreaSeriesDefaults);
39997
40216
  extend(AreaSeries.prototype, {
39998
40217
  singleStacks: false
39999
40218
  });
@@ -40003,100 +40222,6 @@
40003
40222
  * Default Export
40004
40223
  *
40005
40224
  * */
40006
- /* *
40007
- *
40008
- * API Options
40009
- *
40010
- * */
40011
- /**
40012
- * A `area` series. If the [type](#series.area.type) option is not
40013
- * specified, it is inherited from [chart.type](#chart.type).
40014
- *
40015
- * @extends series,plotOptions.area
40016
- * @excluding dataParser, dataURL, useOhlcData
40017
- * @product highcharts highstock
40018
- * @apioption series.area
40019
- */
40020
- /**
40021
- * @see [fillColor](#series.area.fillColor)
40022
- * @see [fillOpacity](#series.area.fillOpacity)
40023
- *
40024
- * @apioption series.area.color
40025
- */
40026
- /**
40027
- * An array of data points for the series. For the `area` series type,
40028
- * points can be given in the following ways:
40029
- *
40030
- * 1. An array of numerical values. In this case, the numerical values will be
40031
- * interpreted as `y` options. The `x` values will be automatically
40032
- * calculated, either starting at 0 and incremented by 1, or from
40033
- * `pointStart` * and `pointInterval` given in the series options. If the
40034
- * axis has categories, these will be used. Example:
40035
- * ```js
40036
- * data: [0, 5, 3, 5]
40037
- * ```
40038
- *
40039
- * 2. An array of arrays with 2 values. In this case, the values correspond to
40040
- * `x,y`. If the first value is a string, it is applied as the name of the
40041
- * point, and the `x` value is inferred.
40042
- * ```js
40043
- * data: [
40044
- * [0, 9],
40045
- * [1, 7],
40046
- * [2, 6]
40047
- * ]
40048
- * ```
40049
- *
40050
- * 3. An array of objects with named values. The following snippet shows only a
40051
- * few settings, see the complete options set below. If the total number of
40052
- * data points exceeds the series'
40053
- * [turboThreshold](#series.area.turboThreshold), this option is not
40054
- * available.
40055
- * ```js
40056
- * data: [{
40057
- * x: 1,
40058
- * y: 9,
40059
- * name: "Point2",
40060
- * color: "#00FF00"
40061
- * }, {
40062
- * x: 1,
40063
- * y: 6,
40064
- * name: "Point1",
40065
- * color: "#FF00FF"
40066
- * }]
40067
- * ```
40068
- *
40069
- * @sample {highcharts} highcharts/chart/reflow-true/
40070
- * Numerical values
40071
- * @sample {highcharts} highcharts/series/data-array-of-arrays/
40072
- * Arrays of numeric x and y
40073
- * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
40074
- * Arrays of datetime x and y
40075
- * @sample {highcharts} highcharts/series/data-array-of-name-value/
40076
- * Arrays of point.name and y
40077
- * @sample {highcharts} highcharts/series/data-array-of-objects/
40078
- * Config objects
40079
- *
40080
- * @type {Array<number|Array<(number|string),(number|null)>|null|*>}
40081
- * @extends series.line.data
40082
- * @product highcharts highstock
40083
- * @apioption series.area.data
40084
- */
40085
- /**
40086
- * @see [color](#series.area.color)
40087
- * @see [fillOpacity](#series.area.fillOpacity)
40088
- *
40089
- * @apioption series.area.fillColor
40090
- */
40091
- /**
40092
- * @see [color](#series.area.color)
40093
- * @see [fillColor](#series.area.fillColor)
40094
- *
40095
- * @default {highcharts} 0.75
40096
- * @default {highstock} 0.75
40097
- * @apioption series.area.fillOpacity
40098
- */
40099
- ''; // Adds doclets above to transpiled
40100
40225
 
40101
40226
  return AreaSeries;
40102
40227
  });
@@ -41055,7 +41180,7 @@
41055
41180
  const { animObject } = A;
41056
41181
  const { parse: color } = Color;
41057
41182
  const { noop } = H;
41058
- const { clamp, defined, extend, fireEvent, isArray, isNumber, merge, pick, objectEach } = U;
41183
+ const { clamp, crisp, defined, extend, fireEvent, isArray, isNumber, merge, pick, objectEach } = U;
41059
41184
  /* *
41060
41185
  *
41061
41186
  * Class
@@ -41087,17 +41212,27 @@
41087
41212
  * Whether to initialize the animation or run it
41088
41213
  */
41089
41214
  animate(init) {
41090
- const series = this, yAxis = this.yAxis, yAxisPos = yAxis.pos, options = series.options, inverted = this.chart.inverted, attr = {}, translateProp = inverted ?
41215
+ const series = this, yAxis = this.yAxis, yAxisPos = yAxis.pos, reversed = yAxis.reversed, options = series.options, { clipOffset, inverted } = this.chart, attr = {}, translateProp = inverted ?
41091
41216
  'translateX' :
41092
41217
  'translateY';
41093
41218
  let translateStart, translatedThreshold;
41094
- if (init) {
41219
+ if (init && clipOffset) {
41095
41220
  attr.scaleY = 0.001;
41096
41221
  translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxisPos, yAxisPos + yAxis.len);
41097
41222
  if (inverted) {
41223
+ // Make sure the columns don't cover the axis line during
41224
+ // entrance animation
41225
+ translatedThreshold += reversed ?
41226
+ -Math.floor(clipOffset[0]) :
41227
+ Math.ceil(clipOffset[2]);
41098
41228
  attr.translateX = translatedThreshold - yAxis.len;
41099
41229
  }
41100
41230
  else {
41231
+ // Make sure the columns don't cover the axis line during
41232
+ // entrance animation
41233
+ translatedThreshold += reversed ?
41234
+ Math.ceil(clipOffset[0]) :
41235
+ -Math.floor(clipOffset[2]);
41101
41236
  attr.translateY = translatedThreshold;
41102
41237
  }
41103
41238
  // Apply final clipping (used in Highcharts Stock) (#7083)
@@ -41217,31 +41352,19 @@
41217
41352
  * @private
41218
41353
  * @function Highcharts.seriesTypes.column#crispCol
41219
41354
  */
41220
- crispCol(x, y, w, h) {
41221
- const borderWidth = this.borderWidth, xCrisp = -(borderWidth % 2 ? 0.5 : 0), yCrisp = borderWidth % 2 ? 0.5 : 1;
41222
- let right;
41355
+ crispCol(x, y, width, height) {
41356
+ const borderWidth = this.borderWidth, inverted = this.chart.inverted, bottom = crisp(y + height, borderWidth, inverted);
41357
+ // Vertical
41358
+ y = crisp(y, borderWidth, inverted);
41359
+ height = bottom - y;
41223
41360
  // Horizontal. We need to first compute the exact right edge, then
41224
41361
  // round it and compute the width from there.
41225
41362
  if (this.options.crisp) {
41226
- right = Math.round(x + w) + xCrisp;
41227
- x = Math.round(x) + xCrisp;
41228
- w = right - x;
41363
+ const right = crisp(x + width, borderWidth);
41364
+ x = crisp(x, borderWidth);
41365
+ width = right - x;
41229
41366
  }
41230
- // Vertical
41231
- const bottom = Math.round(y + h) + yCrisp, fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656
41232
- y = Math.round(y) + yCrisp;
41233
- h = bottom - y;
41234
- // Top edges are exceptions
41235
- if (fromTop && h) { // #5146
41236
- y -= 1;
41237
- h += 1;
41238
- }
41239
- return {
41240
- x: x,
41241
- y: y,
41242
- width: w,
41243
- height: h
41244
- };
41367
+ return { x, y, width, height };
41245
41368
  }
41246
41369
  /**
41247
41370
  * Adjust for missing columns, according to the `centerInCategory`
@@ -41323,14 +41446,11 @@
41323
41446
  translate() {
41324
41447
  const series = this, chart = series.chart, options = series.options, dense = series.dense =
41325
41448
  series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635
41326
- ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width, seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax;
41449
+ ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width, seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax, translatedThreshold = series.translatedThreshold =
41450
+ yAxis.getThreshold(threshold);
41327
41451
  // Postprocessed for border width
41328
41452
  let seriesBarW = series.barW =
41329
- Math.max(seriesPointWidth, 1 + 2 * borderWidth), translatedThreshold = series.translatedThreshold =
41330
- yAxis.getThreshold(threshold);
41331
- if (chart.inverted) {
41332
- translatedThreshold -= 0.5; // #3355
41333
- }
41453
+ Math.max(seriesPointWidth, 1 + 2 * borderWidth);
41334
41454
  // When the pointPadding is 0, we want the columns to be packed
41335
41455
  // tightly, so we allow individual columns to have individual sizes.
41336
41456
  // When pointPadding is greater, we strive for equal-width columns
@@ -41710,7 +41830,7 @@
41710
41830
  * @private
41711
41831
  */
41712
41832
  function alignDataLabel(point, dataLabel, options, alignTo, isNew) {
41713
- const series = this, chart = this.chart, inverted = this.isCartesian && chart.inverted, enabledDataSorting = this.enabledDataSorting, plotX = point.plotX, plotY = point.plotY, rotation = options.rotation || 0, isInsidePlot = defined(plotX) &&
41833
+ const series = this, { chart, enabledDataSorting } = this, inverted = this.isCartesian && chart.inverted, plotX = point.plotX, plotY = point.plotY, rotation = options.rotation || 0, isInsidePlot = defined(plotX) &&
41714
41834
  defined(plotY) &&
41715
41835
  chart.isInsidePlot(plotX, Math.round(plotY), {
41716
41836
  inverted,
@@ -41730,10 +41850,10 @@
41730
41850
  (enabledDataSorting && !justify) ||
41731
41851
  isInsidePlot ||
41732
41852
  (
41733
- // If the data label is inside the align box, it is
41734
- // enough that parts of the align box is inside the
41735
- // plot area (#12370). When stacking, it is always
41736
- // inside regardless of the option (#15148).
41853
+ // If the data label is inside the align box, it is enough
41854
+ // that parts of the align box is inside the plot area
41855
+ // (#12370). When stacking, it is always inside regardless
41856
+ // of the option (#15148).
41737
41857
  pick(options.inside, !!this.options.stacking) &&
41738
41858
  alignTo &&
41739
41859
  chart.isInsidePlot(plotX, inverted ?
@@ -41759,6 +41879,11 @@
41759
41879
  width: 0,
41760
41880
  height: 0
41761
41881
  }, alignTo || {});
41882
+ // Align to plot edges
41883
+ if (options.alignTo === 'plotEdges' && series.isCartesian) {
41884
+ alignTo[inverted ? 'x' : 'y'] = 0;
41885
+ alignTo[inverted ? 'width' : 'height'] = this.yAxis?.len || 0;
41886
+ }
41762
41887
  // Add the text size for alignment calculation
41763
41888
  extend(options, {
41764
41889
  width: bBox.width,
@@ -42096,10 +42221,12 @@
42096
42221
  * @private
42097
42222
  */
42098
42223
  function justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew) {
42099
- const chart = this.chart, align = options.align, verticalAlign = options.verticalAlign, padding = dataLabel.box ? 0 : (dataLabel.padding || 0);
42224
+ const chart = this.chart, align = options.align, verticalAlign = options.verticalAlign, padding = dataLabel.box ? 0 : (dataLabel.padding || 0), horizontalAxis = chart.inverted ? this.yAxis : this.xAxis, horizontalAxisShift = horizontalAxis ?
42225
+ horizontalAxis.left - chart.plotLeft : 0, verticalAxis = chart.inverted ? this.xAxis : this.yAxis, verticalAxisShift = verticalAxis ?
42226
+ verticalAxis.top - chart.plotTop : 0;
42100
42227
  let { x = 0, y = 0 } = options, off, justified;
42101
42228
  // Off left
42102
- off = (alignAttr.x || 0) + padding;
42229
+ off = (alignAttr.x || 0) + padding + horizontalAxisShift;
42103
42230
  if (off < 0) {
42104
42231
  if (align === 'right' && x >= 0) {
42105
42232
  options.align = 'left';
@@ -42111,7 +42238,7 @@
42111
42238
  justified = true;
42112
42239
  }
42113
42240
  // Off right
42114
- off = (alignAttr.x || 0) + bBox.width - padding;
42241
+ off = (alignAttr.x || 0) + bBox.width - padding + horizontalAxisShift;
42115
42242
  if (off > chart.plotWidth) {
42116
42243
  if (align === 'left' && x <= 0) {
42117
42244
  options.align = 'right';
@@ -42123,7 +42250,7 @@
42123
42250
  justified = true;
42124
42251
  }
42125
42252
  // Off top
42126
- off = alignAttr.y + padding;
42253
+ off = alignAttr.y + padding + verticalAxisShift;
42127
42254
  if (off < 0) {
42128
42255
  if (verticalAlign === 'bottom' && y >= 0) {
42129
42256
  options.verticalAlign = 'top';
@@ -42135,7 +42262,7 @@
42135
42262
  justified = true;
42136
42263
  }
42137
42264
  // Off bottom
42138
- off = (alignAttr.y || 0) + bBox.height - padding;
42265
+ off = (alignAttr.y || 0) + bBox.height - padding + verticalAxisShift;
42139
42266
  if (off > chart.plotHeight) {
42140
42267
  if (verticalAlign === 'top' && y <= 0) {
42141
42268
  options.verticalAlign = 'bottom';
@@ -42315,7 +42442,7 @@
42315
42442
  // If parts of the box overshoots outside the plot area, modify
42316
42443
  // the box to center the label inside
42317
42444
  const overshoot = alignTo.y + alignTo.height - yLen;
42318
- if (overshoot > 0 && overshoot < alignTo.height) {
42445
+ if (overshoot > 0 && overshoot < alignTo.height - 1) {
42319
42446
  alignTo.height -= overshoot;
42320
42447
  }
42321
42448
  }
@@ -46876,6 +47003,15 @@
46876
47003
  * @since 6.0.0
46877
47004
  */
46878
47005
  width: 7,
47006
+ /**
47007
+ * Border radius of the handles.
47008
+ *
47009
+ * @sample {highstock} stock/navigator/handles-border-radius/
47010
+ * Border radius on the navigator handles.
47011
+ *
47012
+ * @since 11.4.2
47013
+ */
47014
+ borderRadius: 0,
46879
47015
  /**
46880
47016
  * Height for handles.
46881
47017
  *
@@ -47187,6 +47323,7 @@
47187
47323
  tickLength: 0,
47188
47324
  lineWidth: 0,
47189
47325
  gridLineColor: "#e6e6e6" /* Palette.neutralColor10 */,
47326
+ id: 'navigator-x-axis',
47190
47327
  gridLineWidth: 1,
47191
47328
  tickPixelInterval: 200,
47192
47329
  labels: {
@@ -47240,6 +47377,7 @@
47240
47377
  startOnTick: false,
47241
47378
  endOnTick: false,
47242
47379
  minPadding: 0.1,
47380
+ id: 'navigator-y-axis',
47243
47381
  maxPadding: 0.1,
47244
47382
  labels: {
47245
47383
  enabled: false
@@ -47278,7 +47416,7 @@
47278
47416
 
47279
47417
  return NavigatorDefaults;
47280
47418
  });
47281
- _registerModule(_modules, 'Stock/Navigator/NavigatorSymbols.js', [], function () {
47419
+ _registerModule(_modules, 'Stock/Navigator/NavigatorSymbols.js', [_modules['Core/Renderer/SVG/Symbols.js'], _modules['Core/Utilities.js']], function (rect, U) {
47282
47420
  /* *
47283
47421
  *
47284
47422
  * (c) 2010-2024 Torstein Honsi
@@ -47288,6 +47426,7 @@
47288
47426
  * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
47289
47427
  *
47290
47428
  * */
47429
+ const { relativeLength } = U;
47291
47430
  /* *
47292
47431
  *
47293
47432
  * Constants
@@ -47298,18 +47437,14 @@
47298
47437
  * @private
47299
47438
  */
47300
47439
  function navigatorHandle(_x, _y, width, height, options = {}) {
47301
- const halfWidth = options.width ? options.width / 2 : width, markerPosition = Math.round(halfWidth / 3) + 0.5;
47440
+ const halfWidth = options.width ? options.width / 2 : width, markerPosition = 1.5, r = relativeLength(options.borderRadius || 0, Math.min(halfWidth * 2, height));
47302
47441
  height = options.height || height;
47303
47442
  return [
47304
- ['M', -halfWidth - 1, 0.5],
47305
- ['L', halfWidth, 0.5],
47306
- ['L', halfWidth, height + 0.5],
47307
- ['L', -halfWidth - 1, height + 0.5],
47308
- ['L', -halfWidth - 1, 0.5],
47309
- ['M', -markerPosition, 4],
47310
- ['L', -markerPosition, height - 3],
47311
- ['M', markerPosition - 1, 4],
47312
- ['L', markerPosition - 1, height - 3]
47443
+ ['M', -markerPosition, height / 2 - 3.5],
47444
+ ['L', -markerPosition, height / 2 + 4.5],
47445
+ ['M', markerPosition - 1, height / 2 - 3.5],
47446
+ ['L', markerPosition - 1, height / 2 + 4.5],
47447
+ ...rect.rect(-halfWidth - 1, 0.5, halfWidth * 2 + 1, height, { r })
47313
47448
  ];
47314
47449
  }
47315
47450
  /* *
@@ -47862,7 +47997,7 @@
47862
47997
  *
47863
47998
  * */
47864
47999
  const { defaultOptions } = D;
47865
- const { addEvent, correctFloat, defined, destroyObjectProperties, fireEvent, merge, pick, removeEvent } = U;
48000
+ const { addEvent, correctFloat, crisp, defined, destroyObjectProperties, fireEvent, merge, pick, removeEvent } = U;
47866
48001
  /* *
47867
48002
  *
47868
48003
  * Constants
@@ -48094,9 +48229,8 @@
48094
48229
  rect.attr(rect.crisp({
48095
48230
  x: -0.5,
48096
48231
  y: -0.5,
48097
- // +1 to compensate for crispifying in rect method
48098
- width: size + 1,
48099
- height: size + 1,
48232
+ width: size,
48233
+ height: size,
48100
48234
  r: options.buttonBorderRadius
48101
48235
  }, rect.strokeWidth()));
48102
48236
  // Button arrow
@@ -48306,8 +48440,8 @@
48306
48440
  const trackBorderWidth = scroller.trackBorderWidth =
48307
48441
  scroller.track.strokeWidth();
48308
48442
  scroller.track.attr({
48309
- x: -trackBorderWidth % 2 / 2,
48310
- y: -trackBorderWidth % 2 / 2
48443
+ x: -crisp(0, trackBorderWidth),
48444
+ y: -crisp(0, trackBorderWidth)
48311
48445
  });
48312
48446
  // Draw the scrollbar itself
48313
48447
  scroller.scrollbarGroup = renderer.g().add(group);
@@ -48341,7 +48475,7 @@
48341
48475
  });
48342
48476
  }
48343
48477
  scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth();
48344
- scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2);
48478
+ scroller.scrollbarGroup.translate(-crisp(0, scroller.scrollbarStrokeWidth), -crisp(0, scroller.scrollbarStrokeWidth));
48345
48479
  // Draw the buttons:
48346
48480
  scroller.drawScrollbarButton(0);
48347
48481
  scroller.drawScrollbarButton(1);
@@ -49343,8 +49477,6 @@
49343
49477
  ordinal: baseXaxis.options.ordinal,
49344
49478
  overscroll: baseXaxis.options.overscroll
49345
49479
  }, navigatorOptions.xAxis, {
49346
- id: 'navigator-x-axis',
49347
- yAxis: 'navigator-y-axis',
49348
49480
  type: 'datetime',
49349
49481
  index: xAxisIndex,
49350
49482
  isInternal: true,
@@ -49363,7 +49495,6 @@
49363
49495
  height: height
49364
49496
  }), 'xAxis');
49365
49497
  navigator.yAxis = new Axis(chart, merge(navigatorOptions.yAxis, {
49366
- id: 'navigator-y-axis',
49367
49498
  alignTicks: false,
49368
49499
  offset: 0,
49369
49500
  index: yAxisIndex,
@@ -49515,8 +49646,8 @@
49515
49646
  linkedTo: null,
49516
49647
  group: 'nav',
49517
49648
  padXAxis: false,
49518
- xAxis: 'navigator-x-axis',
49519
- yAxis: 'navigator-y-axis',
49649
+ xAxis: this.navigatorOptions.xAxis?.id,
49650
+ yAxis: this.navigatorOptions.yAxis?.id,
49520
49651
  showInLegend: false,
49521
49652
  stacking: void 0,
49522
49653
  isInternal: true,
@@ -50440,7 +50571,7 @@
50440
50571
  * */
50441
50572
  const { defaultOptions } = D;
50442
50573
  const { composed } = H;
50443
- const { addEvent, defined, extend, find, isNumber, merge, pick, pushUnique } = U;
50574
+ const { addEvent, defined, extend, isNumber, merge, pick, pushUnique } = U;
50444
50575
  /* *
50445
50576
  *
50446
50577
  * Constants
@@ -50524,13 +50655,13 @@
50524
50655
  if (pushUnique(composed, 'RangeSelector')) {
50525
50656
  const chartProto = ChartClass.prototype;
50526
50657
  AxisClass.prototype.minFromRange = axisMinFromRange;
50527
- addEvent(ChartClass, 'afterGetContainer', onChartAfterGetContainer);
50658
+ addEvent(ChartClass, 'afterGetContainer', createRangeSelector);
50528
50659
  addEvent(ChartClass, 'beforeRender', onChartBeforeRender);
50529
50660
  addEvent(ChartClass, 'destroy', onChartDestroy);
50530
50661
  addEvent(ChartClass, 'getMargins', onChartGetMargins);
50531
- addEvent(ChartClass, 'render', onChartRender);
50662
+ addEvent(ChartClass, 'redraw', redrawRangeSelector);
50532
50663
  addEvent(ChartClass, 'update', onChartUpdate);
50533
- chartProto.callbacks.push(onChartCallback);
50664
+ chartProto.callbacks.push(redrawRangeSelector);
50534
50665
  extend(defaultOptions, { rangeSelector: RangeSelectorDefaults.rangeSelector });
50535
50666
  extend(defaultOptions.lang, RangeSelectorDefaults.lang);
50536
50667
  }
@@ -50539,7 +50670,7 @@
50539
50670
  * Initialize rangeselector for stock charts
50540
50671
  * @private
50541
50672
  */
50542
- function onChartAfterGetContainer() {
50673
+ function createRangeSelector() {
50543
50674
  if (this.options.rangeSelector &&
50544
50675
  this.options.rangeSelector.enabled) {
50545
50676
  this.rangeSelector = new RangeSelectorConstructor(this);
@@ -50549,18 +50680,12 @@
50549
50680
  * @private
50550
50681
  */
50551
50682
  function onChartBeforeRender() {
50552
- const chart = this, axes = chart.axes, rangeSelector = chart.rangeSelector;
50683
+ const chart = this, rangeSelector = chart.rangeSelector;
50553
50684
  if (rangeSelector) {
50554
50685
  if (isNumber(rangeSelector.deferredYTDClick)) {
50555
50686
  rangeSelector.clickButton(rangeSelector.deferredYTDClick);
50556
50687
  delete rangeSelector.deferredYTDClick;
50557
50688
  }
50558
- axes.forEach((axis) => {
50559
- axis.updateNames();
50560
- axis.setScale();
50561
- });
50562
- chart.getAxisMargins();
50563
- rangeSelector.render();
50564
50689
  const verticalAlign = rangeSelector.options.verticalAlign;
50565
50690
  if (!rangeSelector.options.floating) {
50566
50691
  if (verticalAlign === 'bottom') {
@@ -50572,53 +50697,34 @@
50572
50697
  }
50573
50698
  }
50574
50699
  }
50575
- /**
50576
- * @private
50577
- */
50578
- function onChartCallback(chart) {
50579
- let extremes, legend, alignTo, verticalAlign;
50580
- const rangeSelector = chart.rangeSelector, redraw = () => {
50581
- if (rangeSelector) {
50582
- extremes = chart.xAxis[0].getExtremes();
50583
- legend = chart.legend;
50584
- verticalAlign = (rangeSelector &&
50585
- rangeSelector.options.verticalAlign);
50586
- if (isNumber(extremes.min)) {
50587
- rangeSelector.render(extremes.min, extremes.max);
50588
- }
50589
- // Re-align the legend so that it's below the rangeselector
50590
- if (legend.display &&
50591
- verticalAlign === 'top' &&
50592
- verticalAlign === legend.options.verticalAlign) {
50593
- // Create a new alignment box for the legend.
50594
- alignTo = merge(chart.spacingBox);
50595
- if (legend.options.layout === 'vertical') {
50596
- alignTo.y = chart.plotTop;
50597
- }
50598
- else {
50599
- alignTo.y += rangeSelector.getHeight();
50600
- }
50601
- legend.group.placed = false; // Don't animate the alignment.
50602
- legend.align(alignTo);
50603
- }
50700
+ function redrawRangeSelector() {
50701
+ const chart = this;
50702
+ const rangeSelector = this.rangeSelector;
50703
+ if (!rangeSelector) {
50704
+ return;
50705
+ }
50706
+ let alignTo;
50707
+ const extremes = chart.xAxis[0].getExtremes();
50708
+ const legend = chart.legend;
50709
+ const verticalAlign = (rangeSelector &&
50710
+ rangeSelector.options.verticalAlign);
50711
+ if (isNumber(extremes.min)) {
50712
+ rangeSelector.render(extremes.min, extremes.max);
50713
+ }
50714
+ // Re-align the legend so that it's below the rangeselector
50715
+ if (legend.display &&
50716
+ verticalAlign === 'top' &&
50717
+ verticalAlign === legend.options.verticalAlign) {
50718
+ // Create a new alignment box for the legend.
50719
+ alignTo = merge(chart.spacingBox);
50720
+ if (legend.options.layout === 'vertical') {
50721
+ alignTo.y = chart.plotTop;
50604
50722
  }
50605
- };
50606
- if (rangeSelector) {
50607
- const events = find(chartDestroyEvents, (e) => e[0] === chart);
50608
- if (!events) {
50609
- chartDestroyEvents.push([chart, [
50610
- // Redraw the scroller on setExtremes
50611
- addEvent(chart.xAxis[0], 'afterSetExtremes', function (e) {
50612
- if (rangeSelector) {
50613
- rangeSelector.render(e.min, e.max);
50614
- }
50615
- }),
50616
- // Redraw the scroller chart resize
50617
- addEvent(chart, 'redraw', redraw)
50618
- ]]);
50723
+ else {
50724
+ alignTo.y += rangeSelector.getHeight();
50619
50725
  }
50620
- // Do it now
50621
- redraw();
50726
+ legend.group.placed = false; // Don't animate the alignment.
50727
+ legend.align(alignTo);
50622
50728
  }
50623
50729
  }
50624
50730
  /**
@@ -50650,22 +50756,6 @@
50650
50756
  }
50651
50757
  }
50652
50758
  }
50653
- /**
50654
- * @private
50655
- */
50656
- function onChartRender() {
50657
- const chart = this, rangeSelector = chart.rangeSelector;
50658
- if (rangeSelector && !rangeSelector.options.floating) {
50659
- rangeSelector.render();
50660
- const verticalAlign = rangeSelector.options.verticalAlign;
50661
- if (verticalAlign === 'bottom') {
50662
- this.extraBottomMargin = true;
50663
- }
50664
- else if (verticalAlign !== 'middle') {
50665
- this.extraTopMargin = true;
50666
- }
50667
- }
50668
- }
50669
50759
  /**
50670
50760
  * @private
50671
50761
  */
@@ -50682,7 +50772,6 @@
50682
50772
  this.extraBottomMargin = false;
50683
50773
  this.extraTopMargin = false;
50684
50774
  if (rangeSelector) {
50685
- onChartCallback(this);
50686
50775
  const verticalAlign = (optionsRangeSelector &&
50687
50776
  optionsRangeSelector.verticalAlign) || (rangeSelector.options && rangeSelector.options.verticalAlign);
50688
50777
  if (!rangeSelector.options.floating) {
@@ -50710,7 +50799,1046 @@
50710
50799
 
50711
50800
  return RangeSelectorComposition;
50712
50801
  });
50713
- _registerModule(_modules, 'Stock/RangeSelector/RangeSelector.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Defaults.js'], _modules['Core/Globals.js'], _modules['Stock/RangeSelector/RangeSelectorComposition.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js']], function (Axis, D, H, RangeSelectorComposition, SVGElement, U) {
50802
+ _registerModule(_modules, 'Core/Axis/OrdinalAxis.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Globals.js'], _modules['Core/Series/Series.js'], _modules['Core/Utilities.js']], function (Axis, H, Series, U) {
50803
+ /* *
50804
+ *
50805
+ * (c) 2010-2024 Torstein Honsi
50806
+ *
50807
+ * License: www.highcharts.com/license
50808
+ *
50809
+ * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
50810
+ *
50811
+ * */
50812
+ const { addEvent, correctFloat, css, defined, error, isNumber, pick, timeUnits, isString } = U;
50813
+ /* *
50814
+ *
50815
+ * Composition
50816
+ *
50817
+ * */
50818
+ /**
50819
+ * Extends the axis with ordinal support.
50820
+ * @private
50821
+ */
50822
+ var OrdinalAxis;
50823
+ (function (OrdinalAxis) {
50824
+ /* *
50825
+ *
50826
+ * Declarations
50827
+ *
50828
+ * */
50829
+ /* *
50830
+ *
50831
+ * Functions
50832
+ *
50833
+ * */
50834
+ /**
50835
+ * Extends the axis with ordinal support.
50836
+ *
50837
+ * @private
50838
+ *
50839
+ * @param AxisClass
50840
+ * Axis class to extend.
50841
+ *
50842
+ * @param ChartClass
50843
+ * Chart class to use.
50844
+ *
50845
+ * @param SeriesClass
50846
+ * Series class to use.
50847
+ */
50848
+ function compose(AxisClass, SeriesClass, ChartClass) {
50849
+ const axisProto = AxisClass.prototype;
50850
+ if (!axisProto.ordinal2lin) {
50851
+ axisProto.getTimeTicks = getTimeTicks;
50852
+ axisProto.index2val = index2val;
50853
+ axisProto.lin2val = lin2val;
50854
+ axisProto.val2lin = val2lin;
50855
+ // Record this to prevent overwriting by broken-axis module (#5979)
50856
+ axisProto.ordinal2lin = axisProto.val2lin;
50857
+ addEvent(AxisClass, 'afterInit', onAxisAfterInit);
50858
+ addEvent(AxisClass, 'foundExtremes', onAxisFoundExtremes);
50859
+ addEvent(AxisClass, 'afterSetScale', onAxisAfterSetScale);
50860
+ addEvent(AxisClass, 'initialAxisTranslation', onAxisInitialAxisTranslation);
50861
+ addEvent(ChartClass, 'pan', onChartPan);
50862
+ addEvent(SeriesClass, 'updatedData', onSeriesUpdatedData);
50863
+ }
50864
+ return AxisClass;
50865
+ }
50866
+ OrdinalAxis.compose = compose;
50867
+ /**
50868
+ * In an ordinal axis, there might be areas with dense concentrations of
50869
+ * points, then large gaps between some. Creating equally distributed
50870
+ * ticks over this entire range may lead to a huge number of ticks that
50871
+ * will later be removed. So instead, break the positions up in
50872
+ * segments, find the tick positions for each segment then concatenize
50873
+ * them. This method is used from both data grouping logic and X axis
50874
+ * tick position logic.
50875
+ * @private
50876
+ */
50877
+ function getTimeTicks(normalizedInterval, min, max, startOfWeek, positions = [], closestDistance = 0, findHigherRanks) {
50878
+ const higherRanks = {}, tickPixelIntervalOption = this.options.tickPixelInterval, time = this.chart.time,
50879
+ // Record all the start positions of a segment, to use when
50880
+ // deciding what's a gap in the data.
50881
+ segmentStarts = [];
50882
+ let end, segmentPositions, hasCrossedHigherRank, info, outsideMax, start = 0, groupPositions = [], lastGroupPosition = -Number.MAX_VALUE;
50883
+ // The positions are not always defined, for example for ordinal
50884
+ // positions when data has regular interval (#1557, #2090)
50885
+ if ((!this.options.ordinal && !this.options.breaks) ||
50886
+ !positions ||
50887
+ positions.length < 3 ||
50888
+ typeof min === 'undefined') {
50889
+ return time.getTimeTicks.apply(time, arguments);
50890
+ }
50891
+ // Analyze the positions array to split it into segments on gaps
50892
+ // larger than 5 times the closest distance. The closest distance is
50893
+ // already found at this point, so we reuse that instead of
50894
+ // computing it again.
50895
+ const posLength = positions.length;
50896
+ for (end = 0; end < posLength; end++) {
50897
+ outsideMax = end && positions[end - 1] > max;
50898
+ if (positions[end] < min) { // Set the last position before min
50899
+ start = end;
50900
+ }
50901
+ if (end === posLength - 1 ||
50902
+ positions[end + 1] - positions[end] > closestDistance * 5 ||
50903
+ outsideMax) {
50904
+ // For each segment, calculate the tick positions from the
50905
+ // getTimeTicks utility function. The interval will be the
50906
+ // same regardless of how long the segment is.
50907
+ if (positions[end] > lastGroupPosition) { // #1475
50908
+ segmentPositions = time.getTimeTicks(normalizedInterval, positions[start], positions[end], startOfWeek);
50909
+ // Prevent duplicate groups, for example for multiple
50910
+ // segments within one larger time frame (#1475)
50911
+ while (segmentPositions.length &&
50912
+ segmentPositions[0] <= lastGroupPosition) {
50913
+ segmentPositions.shift();
50914
+ }
50915
+ if (segmentPositions.length) {
50916
+ lastGroupPosition =
50917
+ segmentPositions[segmentPositions.length - 1];
50918
+ }
50919
+ segmentStarts.push(groupPositions.length);
50920
+ groupPositions = groupPositions.concat(segmentPositions);
50921
+ }
50922
+ // Set start of next segment
50923
+ start = end + 1;
50924
+ }
50925
+ if (outsideMax) {
50926
+ break;
50927
+ }
50928
+ }
50929
+ // Get the grouping info from the last of the segments. The info is
50930
+ // the same for all segments.
50931
+ if (segmentPositions) {
50932
+ info = segmentPositions.info;
50933
+ // Optionally identify ticks with higher rank, for example
50934
+ // when the ticks have crossed midnight.
50935
+ if (findHigherRanks && info.unitRange <= timeUnits.hour) {
50936
+ end = groupPositions.length - 1;
50937
+ // Compare points two by two
50938
+ for (start = 1; start < end; start++) {
50939
+ if (time.dateFormat('%d', groupPositions[start]) !==
50940
+ time.dateFormat('%d', groupPositions[start - 1])) {
50941
+ higherRanks[groupPositions[start]] = 'day';
50942
+ hasCrossedHigherRank = true;
50943
+ }
50944
+ }
50945
+ // If the complete array has crossed midnight, we want
50946
+ // to mark the first positions also as higher rank
50947
+ if (hasCrossedHigherRank) {
50948
+ higherRanks[groupPositions[0]] = 'day';
50949
+ }
50950
+ info.higherRanks = higherRanks;
50951
+ }
50952
+ // Save the info
50953
+ info.segmentStarts = segmentStarts;
50954
+ groupPositions.info = info;
50955
+ }
50956
+ else {
50957
+ error(12, false, this.chart);
50958
+ }
50959
+ // Don't show ticks within a gap in the ordinal axis, where the
50960
+ // space between two points is greater than a portion of the tick
50961
+ // pixel interval
50962
+ if (findHigherRanks && defined(tickPixelIntervalOption)) {
50963
+ const length = groupPositions.length, translatedArr = [], distances = [];
50964
+ let itemToRemove, translated, lastTranslated, medianDistance, distance, i = length;
50965
+ // Find median pixel distance in order to keep a reasonably even
50966
+ // distance between ticks (#748)
50967
+ while (i--) {
50968
+ translated = this.translate(groupPositions[i]);
50969
+ if (lastTranslated) {
50970
+ distances[i] = lastTranslated - translated;
50971
+ }
50972
+ translatedArr[i] = lastTranslated = translated;
50973
+ }
50974
+ distances.sort((a, b) => a - b);
50975
+ medianDistance = distances[Math.floor(distances.length / 2)];
50976
+ if (medianDistance < tickPixelIntervalOption * 0.6) {
50977
+ medianDistance = null;
50978
+ }
50979
+ // Now loop over again and remove ticks where needed
50980
+ i = groupPositions[length - 1] > max ? length - 1 : length; // #817
50981
+ lastTranslated = void 0;
50982
+ while (i--) {
50983
+ translated = translatedArr[i];
50984
+ distance = Math.abs(lastTranslated - translated);
50985
+ // #4175 - when axis is reversed, the distance, is negative but
50986
+ // tickPixelIntervalOption positive, so we need to compare the
50987
+ // same values
50988
+ // Remove ticks that are closer than 0.6 times the pixel
50989
+ // interval from the one to the right, but not if it is close to
50990
+ // the median distance (#748).
50991
+ if (lastTranslated &&
50992
+ distance < tickPixelIntervalOption * 0.8 &&
50993
+ (medianDistance === null || distance < medianDistance * 0.8)) {
50994
+ // Is this a higher ranked position with a normal
50995
+ // position to the right?
50996
+ if (higherRanks[groupPositions[i]] &&
50997
+ !higherRanks[groupPositions[i + 1]]) {
50998
+ // Yes: remove the lower ranked neighbour to the
50999
+ // right
51000
+ itemToRemove = i + 1;
51001
+ lastTranslated = translated; // #709
51002
+ }
51003
+ else {
51004
+ // No: remove this one
51005
+ itemToRemove = i;
51006
+ }
51007
+ groupPositions.splice(itemToRemove, 1);
51008
+ }
51009
+ else {
51010
+ lastTranslated = translated;
51011
+ }
51012
+ }
51013
+ }
51014
+ return groupPositions;
51015
+ }
51016
+ /**
51017
+ * Get axis position of given index of the extended ordinal positions.
51018
+ * Used only when panning an ordinal axis.
51019
+ *
51020
+ * @private
51021
+ * @function Highcharts.Axis#index2val
51022
+ * @param {number} index
51023
+ * The index value of searched point
51024
+ */
51025
+ function index2val(index) {
51026
+ const axis = this, ordinal = axis.ordinal,
51027
+ // Context could be changed to extendedOrdinalPositions.
51028
+ ordinalPositions = ordinal.positions;
51029
+ // The visible range contains only equally spaced values.
51030
+ if (!ordinalPositions) {
51031
+ return index;
51032
+ }
51033
+ let i = ordinalPositions.length - 1, distance;
51034
+ if (index < 0) { // Out of range, in effect panning to the left
51035
+ index = ordinalPositions[0];
51036
+ }
51037
+ else if (index > i) { // Out of range, panning to the right
51038
+ index = ordinalPositions[i];
51039
+ }
51040
+ else { // Split it up
51041
+ i = Math.floor(index);
51042
+ distance = index - i; // The decimal
51043
+ }
51044
+ if (typeof distance !== 'undefined' &&
51045
+ typeof ordinalPositions[i] !== 'undefined') {
51046
+ return ordinalPositions[i] + (distance ?
51047
+ distance *
51048
+ (ordinalPositions[i + 1] - ordinalPositions[i]) :
51049
+ 0);
51050
+ }
51051
+ return index;
51052
+ }
51053
+ /**
51054
+ * Translate from linear (internal) to axis value.
51055
+ *
51056
+ * @private
51057
+ * @function Highcharts.Axis#lin2val
51058
+ * @param {number} val
51059
+ * The linear abstracted value.
51060
+ */
51061
+ function lin2val(val) {
51062
+ const axis = this, ordinal = axis.ordinal, localMin = axis.old ? axis.old.min : axis.min, localA = axis.old ? axis.old.transA : axis.transA;
51063
+ // Always use extendedPositions (#19816)
51064
+ const positions = ordinal.getExtendedPositions();
51065
+ // In some cases (especially in early stages of the chart creation) the
51066
+ // getExtendedPositions might return undefined.
51067
+ if (positions && positions.length) {
51068
+ // Convert back from modivied value to pixels. // #15970
51069
+ const pixelVal = correctFloat((val - localMin) * localA +
51070
+ axis.minPixelPadding), index = correctFloat(ordinal.getIndexOfPoint(pixelVal, positions)), mantissa = correctFloat(index % 1);
51071
+ // Check if the index is inside position array. If true,
51072
+ // read/approximate value for that exact index.
51073
+ if (index >= 0 && index <= positions.length - 1) {
51074
+ const leftNeighbour = positions[Math.floor(index)], rightNeighbour = positions[Math.ceil(index)], distance = rightNeighbour - leftNeighbour;
51075
+ return positions[Math.floor(index)] + mantissa * distance;
51076
+ }
51077
+ }
51078
+ // If the value is outside positions array, return initial value
51079
+ return val; // #16784
51080
+ }
51081
+ /**
51082
+ * Internal function to calculate the precise index in ordinalPositions
51083
+ * array.
51084
+ * @private
51085
+ */
51086
+ function getIndexInArray(ordinalPositions, val) {
51087
+ const index = OrdinalAxis.Additions.findIndexOf(ordinalPositions, val, true);
51088
+ if (ordinalPositions[index] === val) {
51089
+ return index;
51090
+ }
51091
+ const percent = (val - ordinalPositions[index]) /
51092
+ (ordinalPositions[index + 1] - ordinalPositions[index]);
51093
+ return index + percent;
51094
+ }
51095
+ /**
51096
+ * @private
51097
+ */
51098
+ function onAxisAfterInit() {
51099
+ const axis = this;
51100
+ if (!axis.ordinal) {
51101
+ axis.ordinal = new OrdinalAxis.Additions(axis);
51102
+ }
51103
+ }
51104
+ /**
51105
+ * @private
51106
+ */
51107
+ function onAxisFoundExtremes() {
51108
+ const axis = this, { eventArgs, options } = axis;
51109
+ if (axis.isXAxis &&
51110
+ defined(options.overscroll) &&
51111
+ options.overscroll !== 0 &&
51112
+ isNumber(axis.max) &&
51113
+ isNumber(axis.min)) {
51114
+ if (axis.options.ordinal && !axis.ordinal.originalOrdinalRange) {
51115
+ // Calculate the original ordinal range
51116
+ axis.ordinal.getExtendedPositions(false);
51117
+ }
51118
+ if (axis.max === axis.dataMax &&
51119
+ (
51120
+ // Panning is an exception. We don't want to apply
51121
+ // overscroll when panning over the dataMax
51122
+ eventArgs?.trigger !== 'pan' ||
51123
+ axis.isInternal) &&
51124
+ // Scrollbar buttons are the other execption
51125
+ eventArgs?.trigger !== 'navigator') {
51126
+ const overscroll = axis.ordinal.convertOverscroll(options.overscroll);
51127
+ axis.max += overscroll;
51128
+ // Live data and buttons require translation for the min:
51129
+ if (!axis.isInternal &&
51130
+ defined(axis.userMin) &&
51131
+ eventArgs?.trigger !== 'mousewheel') {
51132
+ axis.min += overscroll;
51133
+ }
51134
+ }
51135
+ }
51136
+ }
51137
+ /**
51138
+ * For ordinal axis, that loads data async, redraw axis after data is
51139
+ * loaded. If we don't do that, axis will have the same extremes as
51140
+ * previously, but ordinal positions won't be calculated. See #10290
51141
+ * @private
51142
+ */
51143
+ function onAxisAfterSetScale() {
51144
+ const axis = this;
51145
+ if (axis.horiz && !axis.isDirty) {
51146
+ axis.isDirty = axis.isOrdinal &&
51147
+ axis.chart.navigator &&
51148
+ !axis.chart.navigator.adaptToUpdatedData;
51149
+ }
51150
+ }
51151
+ /**
51152
+ * @private
51153
+ */
51154
+ function onAxisInitialAxisTranslation() {
51155
+ const axis = this;
51156
+ if (axis.ordinal) {
51157
+ axis.ordinal.beforeSetTickPositions();
51158
+ axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval);
51159
+ }
51160
+ }
51161
+ /**
51162
+ * Extending the Chart.pan method for ordinal axes
51163
+ * @private
51164
+ */
51165
+ function onChartPan(e) {
51166
+ const chart = this, xAxis = chart.xAxis[0], overscroll = xAxis.ordinal.convertOverscroll(xAxis.options.overscroll), chartX = e.originalEvent.chartX, panning = chart.options.chart.panning;
51167
+ let runBase = false;
51168
+ if (panning &&
51169
+ panning.type !== 'y' &&
51170
+ xAxis.options.ordinal &&
51171
+ xAxis.series.length) {
51172
+ const mouseDownX = chart.mouseDownX, extremes = xAxis.getExtremes(), dataMin = extremes.dataMin, dataMax = extremes.dataMax, min = extremes.min, max = extremes.max, hoverPoints = chart.hoverPoints, closestPointRange = (xAxis.closestPointRange ||
51173
+ (xAxis.ordinal && xAxis.ordinal.overscrollPointsRange)), pointPixelWidth = (xAxis.translationSlope *
51174
+ (xAxis.ordinal.slope || closestPointRange)),
51175
+ // How many ordinal units did we move?
51176
+ movedUnits = Math.round((mouseDownX - chartX) / pointPixelWidth),
51177
+ // Get index of all the chart's points
51178
+ extendedOrdinalPositions = xAxis.ordinal.getExtendedPositions(), extendedAxis = {
51179
+ ordinal: {
51180
+ positions: extendedOrdinalPositions,
51181
+ extendedOrdinalPositions: extendedOrdinalPositions
51182
+ }
51183
+ }, index2val = xAxis.index2val, val2lin = xAxis.val2lin;
51184
+ let trimmedRange, ordinalPositions;
51185
+ // Make sure panning to the edges does not decrease the zoomed range
51186
+ if ((min <= dataMin && movedUnits < 0) ||
51187
+ (max + overscroll >= dataMax && movedUnits > 0)) {
51188
+ return;
51189
+ }
51190
+ // We have an ordinal axis, but the data is equally spaced
51191
+ if (!extendedAxis.ordinal.positions) {
51192
+ runBase = true;
51193
+ }
51194
+ else if (Math.abs(movedUnits) > 1) {
51195
+ // Remove active points for shared tooltip
51196
+ if (hoverPoints) {
51197
+ hoverPoints.forEach(function (point) {
51198
+ point.setState();
51199
+ });
51200
+ }
51201
+ // In grouped data series, the last ordinal position represents
51202
+ // the grouped data, which is to the left of the real data max.
51203
+ // If we don't compensate for this, we will be allowed to pan
51204
+ // grouped data series passed the right of the plot area.
51205
+ ordinalPositions = extendedAxis.ordinal.positions;
51206
+ if (dataMax >
51207
+ ordinalPositions[ordinalPositions.length - 1]) {
51208
+ ordinalPositions.push(dataMax);
51209
+ }
51210
+ // Get the new min and max values by getting the ordinal index
51211
+ // for the current extreme, then add the moved units and
51212
+ // translate back to values. This happens on the extended
51213
+ // ordinal positions if the new position is out of range, else
51214
+ // it happens on the current x axis which is smaller and faster.
51215
+ chart.setFixedRange(max - min);
51216
+ trimmedRange = xAxis.navigatorAxis
51217
+ .toFixedRange(void 0, void 0, index2val.apply(extendedAxis, [
51218
+ val2lin.apply(extendedAxis, [min, true]) +
51219
+ movedUnits
51220
+ ]), index2val.apply(extendedAxis, [
51221
+ val2lin.apply(extendedAxis, [max, true]) +
51222
+ movedUnits
51223
+ ]));
51224
+ // Apply it if it is within the available data range
51225
+ if (trimmedRange.min >= Math.min(extremes.dataMin, min) &&
51226
+ trimmedRange.max <= Math.max(dataMax, max) + overscroll) {
51227
+ xAxis.setExtremes(trimmedRange.min, trimmedRange.max, true, false, { trigger: 'pan' });
51228
+ }
51229
+ chart.mouseDownX = chartX; // Set new reference for next run
51230
+ css(chart.container, { cursor: 'move' });
51231
+ }
51232
+ }
51233
+ else {
51234
+ runBase = true;
51235
+ }
51236
+ // Revert to the linear chart.pan version
51237
+ if (runBase || (panning && /y/.test(panning.type))) {
51238
+ if (overscroll) {
51239
+ xAxis.max = xAxis.dataMax + overscroll;
51240
+ }
51241
+ }
51242
+ else {
51243
+ e.preventDefault();
51244
+ }
51245
+ }
51246
+ /**
51247
+ * @private
51248
+ */
51249
+ function onSeriesUpdatedData() {
51250
+ const xAxis = this.xAxis;
51251
+ // Destroy the extended ordinal index on updated data
51252
+ // and destroy extendedOrdinalPositions, #16055.
51253
+ if (xAxis && xAxis.options.ordinal) {
51254
+ delete xAxis.ordinal.index;
51255
+ delete xAxis.ordinal.originalOrdinalRange;
51256
+ }
51257
+ }
51258
+ /**
51259
+ * Translate from a linear axis value to the corresponding ordinal axis
51260
+ * position. If there are no gaps in the ordinal axis this will be the
51261
+ * same. The translated value is the value that the point would have if
51262
+ * the axis was linear, using the same min and max.
51263
+ *
51264
+ * @private
51265
+ * @function Highcharts.Axis#val2lin
51266
+ * @param {number} val
51267
+ * The axis value.
51268
+ * @param {boolean} [toIndex]
51269
+ * Whether to return the index in the ordinalPositions or the new value.
51270
+ */
51271
+ function val2lin(val, toIndex) {
51272
+ const axis = this, ordinal = axis.ordinal, ordinalPositions = ordinal.positions;
51273
+ let slope = ordinal.slope, extendedOrdinalPositions;
51274
+ if (!ordinalPositions) {
51275
+ return val;
51276
+ }
51277
+ const ordinalLength = ordinalPositions.length;
51278
+ let ordinalIndex;
51279
+ // If the searched value is inside visible plotArea, ivastigate the
51280
+ // value basing on ordinalPositions.
51281
+ if (ordinalPositions[0] <= val &&
51282
+ ordinalPositions[ordinalLength - 1] >= val) {
51283
+ ordinalIndex = getIndexInArray(ordinalPositions, val);
51284
+ // Final return value is based on ordinalIndex
51285
+ }
51286
+ else {
51287
+ extendedOrdinalPositions =
51288
+ ordinal.getExtendedPositions &&
51289
+ ordinal.getExtendedPositions();
51290
+ if (!(extendedOrdinalPositions && extendedOrdinalPositions.length)) {
51291
+ return val;
51292
+ }
51293
+ const length = extendedOrdinalPositions.length;
51294
+ if (!slope) {
51295
+ slope =
51296
+ (extendedOrdinalPositions[length - 1] -
51297
+ extendedOrdinalPositions[0]) /
51298
+ length;
51299
+ }
51300
+ // `originalPointReference` is equal to the index of first point of
51301
+ // ordinalPositions in extendedOrdinalPositions.
51302
+ const originalPositionsReference = getIndexInArray(extendedOrdinalPositions, ordinalPositions[0]);
51303
+ // If the searched value is outside the visiblePlotArea,
51304
+ // check if it is inside extendedOrdinalPositions.
51305
+ if (val >= extendedOrdinalPositions[0] &&
51306
+ val <=
51307
+ extendedOrdinalPositions[length - 1]) {
51308
+ // Return Value
51309
+ ordinalIndex = getIndexInArray(extendedOrdinalPositions, val) -
51310
+ originalPositionsReference;
51311
+ }
51312
+ else {
51313
+ if (!toIndex) {
51314
+ // If the value is outside positions array,
51315
+ // return initial value, #16784
51316
+ return val;
51317
+ }
51318
+ // Since ordinal.slope is the average distance between 2
51319
+ // points on visible plotArea, this can be used to calculate
51320
+ // the approximate position of the point, which is outside
51321
+ // the extendedOrdinalPositions.
51322
+ if (val < extendedOrdinalPositions[0]) {
51323
+ const diff = extendedOrdinalPositions[0] - val, approximateIndexOffset = diff / slope;
51324
+ ordinalIndex =
51325
+ -originalPositionsReference -
51326
+ approximateIndexOffset;
51327
+ }
51328
+ else {
51329
+ const diff = val -
51330
+ extendedOrdinalPositions[length - 1], approximateIndexOffset = diff / slope;
51331
+ ordinalIndex =
51332
+ approximateIndexOffset +
51333
+ length -
51334
+ originalPositionsReference;
51335
+ }
51336
+ }
51337
+ }
51338
+ return toIndex ? ordinalIndex : slope * (ordinalIndex || 0) +
51339
+ ordinal.offset;
51340
+ }
51341
+ /* *
51342
+ *
51343
+ * Classes
51344
+ *
51345
+ * */
51346
+ /**
51347
+ * @private
51348
+ */
51349
+ class Additions {
51350
+ /* *
51351
+ *
51352
+ * Constructors
51353
+ *
51354
+ * */
51355
+ /**
51356
+ * @private
51357
+ */
51358
+ constructor(axis) {
51359
+ this.index = {};
51360
+ this.axis = axis;
51361
+ }
51362
+ /* *
51363
+ *
51364
+ * Functions
51365
+ *
51366
+ * */
51367
+ /**
51368
+ * Calculate the ordinal positions before tick positions are calculated.
51369
+ * @private
51370
+ */
51371
+ beforeSetTickPositions() {
51372
+ const axis = this.axis, ordinal = axis.ordinal, extremes = axis.getExtremes(), min = extremes.min, max = extremes.max, hasBreaks = axis.brokenAxis?.hasBreaks, isOrdinal = axis.options.ordinal;
51373
+ let len, uniqueOrdinalPositions, dist, minIndex, maxIndex, slope, i, ordinalPositions = [], overscrollPointsRange = Number.MAX_VALUE, useOrdinal = false, adjustOrdinalExtremesPoints = false, isBoosted = false;
51374
+ // Apply the ordinal logic
51375
+ if (isOrdinal || hasBreaks) { // #4167 YAxis is never ordinal ?
51376
+ let distanceBetweenPoint = 0;
51377
+ axis.series.forEach(function (series, i) {
51378
+ uniqueOrdinalPositions = [];
51379
+ // For an axis with multiple series, check if the distance
51380
+ // between points is identical throughout all series.
51381
+ if (i > 0 &&
51382
+ series.options.id !== 'highcharts-navigator-series' &&
51383
+ series.processedXData.length > 1) {
51384
+ adjustOrdinalExtremesPoints =
51385
+ distanceBetweenPoint !== series.processedXData[1] -
51386
+ series.processedXData[0];
51387
+ }
51388
+ distanceBetweenPoint =
51389
+ series.processedXData[1] - series.processedXData[0];
51390
+ if (series.boosted) {
51391
+ isBoosted = series.boosted;
51392
+ }
51393
+ if (series.reserveSpace() &&
51394
+ (series
51395
+ .takeOrdinalPosition !== false || hasBreaks)) {
51396
+ // Concatenate the processed X data into the existing
51397
+ // positions, or the empty array
51398
+ ordinalPositions = ordinalPositions.concat(series.processedXData);
51399
+ len = ordinalPositions.length;
51400
+ // Remove duplicates (#1588)
51401
+ ordinalPositions.sort(function (a, b) {
51402
+ // Without a custom function it is sorted as strings
51403
+ return a - b;
51404
+ });
51405
+ overscrollPointsRange = Math.min(overscrollPointsRange, pick(
51406
+ // Check for a single-point series:
51407
+ series.closestPointRange, overscrollPointsRange));
51408
+ if (len) {
51409
+ i = 0;
51410
+ while (i < len - 1) {
51411
+ if (ordinalPositions[i] !==
51412
+ ordinalPositions[i + 1]) {
51413
+ uniqueOrdinalPositions.push(ordinalPositions[i + 1]);
51414
+ }
51415
+ i++;
51416
+ }
51417
+ // Check first item:
51418
+ if (uniqueOrdinalPositions[0] !==
51419
+ ordinalPositions[0]) {
51420
+ uniqueOrdinalPositions.unshift(ordinalPositions[0]);
51421
+ }
51422
+ ordinalPositions = uniqueOrdinalPositions;
51423
+ }
51424
+ }
51425
+ });
51426
+ if (!axis.ordinal.originalOrdinalRange) {
51427
+ // Calculate current originalOrdinalRange
51428
+ axis.ordinal.originalOrdinalRange =
51429
+ (ordinalPositions.length - 1) * overscrollPointsRange;
51430
+ }
51431
+ // If the distance between points is not identical throughout
51432
+ // all series, remove the first and last ordinal position to
51433
+ // avoid enabling ordinal logic when it is not needed, #17405.
51434
+ // Only for boosted series because changes are negligible.
51435
+ if (adjustOrdinalExtremesPoints && isBoosted) {
51436
+ ordinalPositions.pop();
51437
+ ordinalPositions.shift();
51438
+ }
51439
+ // Cache the length
51440
+ len = ordinalPositions.length;
51441
+ // Check if we really need the overhead of mapping axis data
51442
+ // against the ordinal positions. If the series consist of
51443
+ // evenly spaced data any way, we don't need any ordinal logic.
51444
+ if (len > 2) { // Two points have equal distance by default
51445
+ dist = ordinalPositions[1] - ordinalPositions[0];
51446
+ i = len - 1;
51447
+ while (i-- && !useOrdinal) {
51448
+ if (ordinalPositions[i + 1] - ordinalPositions[i] !==
51449
+ dist) {
51450
+ useOrdinal = true;
51451
+ }
51452
+ }
51453
+ // When zooming in on a week, prevent axis padding for
51454
+ // weekends even though the data within the week is evenly
51455
+ // spaced.
51456
+ if (!axis.options.keepOrdinalPadding &&
51457
+ (ordinalPositions[0] - min > dist ||
51458
+ (max -
51459
+ ordinalPositions[ordinalPositions.length - 1]) > dist)) {
51460
+ useOrdinal = true;
51461
+ }
51462
+ }
51463
+ else if (axis.options.overscroll) {
51464
+ if (len === 2) {
51465
+ // Exactly two points, distance for overscroll is fixed:
51466
+ overscrollPointsRange =
51467
+ ordinalPositions[1] - ordinalPositions[0];
51468
+ }
51469
+ else if (len === 1) {
51470
+ // We have just one point, closest distance is unknown.
51471
+ // Assume then it is last point and overscrolled range:
51472
+ overscrollPointsRange = axis.ordinal.convertOverscroll(axis.options.overscroll);
51473
+ ordinalPositions = [
51474
+ ordinalPositions[0],
51475
+ ordinalPositions[0] + overscrollPointsRange
51476
+ ];
51477
+ }
51478
+ else {
51479
+ // In case of zooming in on overscrolled range, stick to
51480
+ // the old range:
51481
+ overscrollPointsRange = ordinal.overscrollPointsRange;
51482
+ }
51483
+ }
51484
+ // Record the slope and offset to compute the linear values from
51485
+ // the array index. Since the ordinal positions may exceed the
51486
+ // current range, get the start and end positions within it
51487
+ // (#719, #665b)
51488
+ if (useOrdinal || axis.forceOrdinal) {
51489
+ if (axis.options.overscroll) {
51490
+ ordinal.overscrollPointsRange = overscrollPointsRange;
51491
+ ordinalPositions = ordinalPositions.concat(ordinal.getOverscrollPositions());
51492
+ }
51493
+ // Register
51494
+ ordinal.positions = ordinalPositions;
51495
+ // This relies on the ordinalPositions being set. Use
51496
+ // Math.max and Math.min to prevent padding on either sides
51497
+ // of the data.
51498
+ minIndex = axis.ordinal2lin(// #5979
51499
+ Math.max(min, ordinalPositions[0]), true);
51500
+ maxIndex = Math.max(axis.ordinal2lin(Math.min(max, ordinalPositions[ordinalPositions.length - 1]), true), 1); // #3339
51501
+ // Set the slope and offset of the values compared to the
51502
+ // indices in the ordinal positions.
51503
+ ordinal.slope = slope =
51504
+ (max - min) / (maxIndex - minIndex);
51505
+ ordinal.offset = min - (minIndex * slope);
51506
+ }
51507
+ else {
51508
+ ordinal.overscrollPointsRange = pick(axis.closestPointRange, ordinal.overscrollPointsRange);
51509
+ ordinal.positions = axis.ordinal.slope = ordinal.offset =
51510
+ void 0;
51511
+ }
51512
+ }
51513
+ axis.isOrdinal = isOrdinal && useOrdinal; // #3818, #4196, #4926
51514
+ ordinal.groupIntervalFactor = null; // Reset for next run
51515
+ }
51516
+ /**
51517
+ * Faster way of using the Array.indexOf method.
51518
+ * Works for sorted arrays only with unique values.
51519
+ *
51520
+ * @param {Array} sortedArray
51521
+ * The sorted array inside which we are looking for.
51522
+ * @param {number} key
51523
+ * The key to being found.
51524
+ * @param {boolean} indirectSearch
51525
+ * In case of lack of the point in the array, should return
51526
+ * value be equal to -1 or the closest smaller index.
51527
+ * @private
51528
+ */
51529
+ static findIndexOf(sortedArray, key, indirectSearch) {
51530
+ let start = 0, end = sortedArray.length - 1, middle;
51531
+ while (start < end) {
51532
+ middle = Math.ceil((start + end) / 2);
51533
+ // Key found as the middle element.
51534
+ if (sortedArray[middle] <= key) {
51535
+ // Continue searching to the right.
51536
+ start = middle;
51537
+ }
51538
+ else {
51539
+ // Continue searching to the left.
51540
+ end = middle - 1;
51541
+ }
51542
+ }
51543
+ if (sortedArray[start] === key) {
51544
+ return start;
51545
+ }
51546
+ // Key could not be found.
51547
+ return !indirectSearch ? -1 : start;
51548
+ }
51549
+ /**
51550
+ * Get the ordinal positions for the entire data set. This is necessary
51551
+ * in chart panning because we need to find out what points or data
51552
+ * groups are available outside the visible range. When a panning
51553
+ * operation starts, if an index for the given grouping does not exists,
51554
+ * it is created and cached. This index is deleted on updated data, so
51555
+ * it will be regenerated the next time a panning operation starts.
51556
+ * @private
51557
+ */
51558
+ getExtendedPositions(withOverscroll = true) {
51559
+ const ordinal = this, axis = ordinal.axis, axisProto = axis.constructor.prototype, chart = axis.chart, grouping = axis.series[0]?.currentDataGrouping, key = grouping ?
51560
+ grouping.count + grouping.unitName :
51561
+ 'raw', overscroll = withOverscroll ?
51562
+ axis.ordinal.convertOverscroll(axis.options.overscroll) : 0, extremes = axis.getExtremes();
51563
+ let fakeAxis, fakeSeries = void 0, ordinalIndex = ordinal.index;
51564
+ // If this is the first time, or the ordinal index is deleted by
51565
+ // updatedData,
51566
+ // create it.
51567
+ if (!ordinalIndex) {
51568
+ ordinalIndex = ordinal.index = {};
51569
+ }
51570
+ if (!ordinalIndex[key]) {
51571
+ // Create a fake axis object where the extended ordinal
51572
+ // positions are emulated
51573
+ fakeAxis = {
51574
+ series: [],
51575
+ chart: chart,
51576
+ forceOrdinal: false,
51577
+ getExtremes: function () {
51578
+ return {
51579
+ min: extremes.dataMin,
51580
+ max: extremes.dataMax + overscroll
51581
+ };
51582
+ },
51583
+ applyGrouping: axisProto.applyGrouping,
51584
+ getGroupPixelWidth: axisProto.getGroupPixelWidth,
51585
+ getTimeTicks: axisProto.getTimeTicks,
51586
+ options: {
51587
+ ordinal: true
51588
+ },
51589
+ ordinal: {
51590
+ getGroupIntervalFactor: this.getGroupIntervalFactor
51591
+ },
51592
+ ordinal2lin: axisProto.ordinal2lin,
51593
+ getIndexOfPoint: axisProto.getIndexOfPoint,
51594
+ val2lin: axisProto.val2lin // #2590
51595
+ };
51596
+ fakeAxis.ordinal.axis = fakeAxis;
51597
+ // Add the fake series to hold the full data, then apply
51598
+ // processData to it
51599
+ axis.series.forEach(function (series) {
51600
+ fakeSeries = {
51601
+ xAxis: fakeAxis,
51602
+ xData: series.xData.slice(),
51603
+ chart: chart,
51604
+ groupPixelWidth: series.groupPixelWidth,
51605
+ destroyGroupedData: H.noop,
51606
+ getProcessedData: Series.prototype.getProcessedData,
51607
+ applyGrouping: Series.prototype.applyGrouping,
51608
+ reserveSpace: Series.prototype.reserveSpace,
51609
+ visible: series.visible
51610
+ };
51611
+ if (withOverscroll) {
51612
+ fakeSeries.xData = fakeSeries.xData.concat(ordinal.getOverscrollPositions());
51613
+ }
51614
+ fakeSeries.options = {
51615
+ dataGrouping: grouping ? {
51616
+ firstAnchor: series.options.dataGrouping?.firstAnchor,
51617
+ anchor: series.options.dataGrouping?.anchor,
51618
+ lastAnchor: series.options.dataGrouping?.firstAnchor,
51619
+ enabled: true,
51620
+ forced: true,
51621
+ // Doesn't matter which, use the fastest
51622
+ approximation: 'open',
51623
+ units: [[
51624
+ grouping.unitName,
51625
+ [grouping.count]
51626
+ ]]
51627
+ } : {
51628
+ enabled: false
51629
+ }
51630
+ };
51631
+ fakeAxis.series.push(fakeSeries);
51632
+ series.processData.apply(fakeSeries);
51633
+ });
51634
+ fakeAxis.applyGrouping({ hasExtremesChanged: true });
51635
+ // Force to use the ordinal when points are evenly spaced (e.g.
51636
+ // weeks), #3825.
51637
+ if ((fakeSeries?.closestPointRange !==
51638
+ fakeSeries?.basePointRange) &&
51639
+ fakeSeries.currentDataGrouping) {
51640
+ fakeAxis.forceOrdinal = true;
51641
+ }
51642
+ // Run beforeSetTickPositions to compute the ordinalPositions
51643
+ axis.ordinal.beforeSetTickPositions.apply({ axis: fakeAxis });
51644
+ if (!axis.ordinal.originalOrdinalRange &&
51645
+ fakeAxis.ordinal.originalOrdinalRange) {
51646
+ axis.ordinal.originalOrdinalRange =
51647
+ fakeAxis.ordinal.originalOrdinalRange;
51648
+ }
51649
+ // Cache it
51650
+ ordinalIndex[key] = fakeAxis.ordinal.positions;
51651
+ }
51652
+ return ordinalIndex[key];
51653
+ }
51654
+ /**
51655
+ * Find the factor to estimate how wide the plot area would have been if
51656
+ * ordinal gaps were included. This value is used to compute an imagined
51657
+ * plot width in order to establish the data grouping interval.
51658
+ *
51659
+ * A real world case is the intraday-candlestick example. Without this
51660
+ * logic, it would show the correct data grouping when viewing a range
51661
+ * within each day, but once moving the range to include the gap between
51662
+ * two days, the interval would include the cut-away night hours and the
51663
+ * data grouping would be wrong. So the below method tries to compensate
51664
+ * by identifying the most common point interval, in this case days.
51665
+ *
51666
+ * An opposite case is presented in issue #718. We have a long array of
51667
+ * daily data, then one point is appended one hour after the last point.
51668
+ * We expect the data grouping not to change.
51669
+ *
51670
+ * In the future, if we find cases where this estimation doesn't work
51671
+ * optimally, we might need to add a second pass to the data grouping
51672
+ * logic, where we do another run with a greater interval if the number
51673
+ * of data groups is more than a certain fraction of the desired group
51674
+ * count.
51675
+ * @private
51676
+ */
51677
+ getGroupIntervalFactor(xMin, xMax, series) {
51678
+ const ordinal = this, processedXData = series.processedXData, len = processedXData.length, distances = [];
51679
+ let median, i, groupIntervalFactor = ordinal.groupIntervalFactor;
51680
+ // Only do this computation for the first series, let the other
51681
+ // inherit it (#2416)
51682
+ if (!groupIntervalFactor) {
51683
+ // Register all the distances in an array
51684
+ for (i = 0; i < len - 1; i++) {
51685
+ distances[i] = (processedXData[i + 1] -
51686
+ processedXData[i]);
51687
+ }
51688
+ // Sort them and find the median
51689
+ distances.sort(function (a, b) {
51690
+ return a - b;
51691
+ });
51692
+ median = distances[Math.floor(len / 2)];
51693
+ // Compensate for series that don't extend through the entire
51694
+ // axis extent. #1675.
51695
+ xMin = Math.max(xMin, processedXData[0]);
51696
+ xMax = Math.min(xMax, processedXData[len - 1]);
51697
+ ordinal.groupIntervalFactor = groupIntervalFactor =
51698
+ (len * median) / (xMax - xMin);
51699
+ }
51700
+ // Return the factor needed for data grouping
51701
+ return groupIntervalFactor;
51702
+ }
51703
+ /**
51704
+ * Get index of point inside the ordinal positions array.
51705
+ *
51706
+ * @private
51707
+ * @param {number} val
51708
+ * The pixel value of a point.
51709
+ *
51710
+ * @param {Array<number>} [ordinalArray]
51711
+ * An array of all points available on the axis for the given data set.
51712
+ * Either ordinalPositions if the value is inside the plotArea or
51713
+ * extendedOrdinalPositions if not.
51714
+ */
51715
+ getIndexOfPoint(val, ordinalArray) {
51716
+ const ordinal = this, axis = ordinal.axis;
51717
+ let firstPointVal = 0;
51718
+ // Check whether the series has at least one point inside the chart
51719
+ const hasPointsInside = function (series) {
51720
+ const { min, max } = axis;
51721
+ if (defined(min) && defined(max)) {
51722
+ return series.points.some((point) => point.x >= min && point.x <= max);
51723
+ }
51724
+ return false;
51725
+ };
51726
+ let firstPointX;
51727
+ // When more series assign to axis, find the smallest one, #15987.
51728
+ axis.series.forEach((series) => {
51729
+ const firstPoint = series.points?.[0];
51730
+ if (defined(firstPoint?.plotX) &&
51731
+ (firstPoint.plotX < firstPointX ||
51732
+ !defined(firstPointX)) &&
51733
+ hasPointsInside(series)) {
51734
+ firstPointX = firstPoint.plotX;
51735
+ firstPointVal = firstPoint.x;
51736
+ }
51737
+ });
51738
+ // If undefined, give a default value
51739
+ firstPointX ?? (firstPointX = axis.minPixelPadding);
51740
+ // Distance in pixels between two points on the ordinal axis in the
51741
+ // current zoom.
51742
+ const ordinalPointPixelInterval = axis.translationSlope * (ordinal.slope ||
51743
+ axis.closestPointRange ||
51744
+ ordinal.overscrollPointsRange),
51745
+ // `toValue` for the first point.
51746
+ shiftIndex = correctFloat((val - firstPointX) / ordinalPointPixelInterval);
51747
+ return Additions.findIndexOf(ordinalArray, firstPointVal, true) + shiftIndex;
51748
+ }
51749
+ /**
51750
+ * Get ticks for an ordinal axis within a range where points don't
51751
+ * exist. It is required when overscroll is enabled. We can't base on
51752
+ * points, because we may not have any, so we use approximated
51753
+ * pointRange and generate these ticks between Axis.dataMax,
51754
+ * Axis.dataMax + Axis.overscroll evenly spaced. Used in panning and
51755
+ * navigator scrolling.
51756
+ * @private
51757
+ */
51758
+ getOverscrollPositions() {
51759
+ const ordinal = this, axis = ordinal.axis, extraRange = ordinal.convertOverscroll(axis.options.overscroll), distance = ordinal.overscrollPointsRange, positions = [];
51760
+ let max = axis.dataMax;
51761
+ if (defined(distance)) {
51762
+ // Max + pointRange because we need to scroll to the last
51763
+ while (max <= axis.dataMax + extraRange) {
51764
+ max += distance;
51765
+ positions.push(max);
51766
+ }
51767
+ }
51768
+ return positions;
51769
+ }
51770
+ /**
51771
+ * Make the tick intervals closer because the ordinal gaps make the
51772
+ * ticks spread out or cluster.
51773
+ * @private
51774
+ */
51775
+ postProcessTickInterval(tickInterval) {
51776
+ // Problem: https://jsfiddle.net/highcharts/FQm4E/1/. This is a case
51777
+ // where this algorithm doesn't work optimally. In this case, the
51778
+ // tick labels are spread out per week, but all the gaps reside
51779
+ // within weeks. So we have a situation where the labels are courser
51780
+ // than the ordinal gaps, and thus the tick interval should not be
51781
+ // altered.
51782
+ const ordinal = this, axis = ordinal.axis, ordinalSlope = ordinal.slope;
51783
+ let ret;
51784
+ if (ordinalSlope) {
51785
+ if (!axis.options.breaks) {
51786
+ ret = (tickInterval /
51787
+ (ordinalSlope / axis.closestPointRange));
51788
+ }
51789
+ else {
51790
+ ret = axis.closestPointRange || tickInterval; // #7275
51791
+ }
51792
+ }
51793
+ else {
51794
+ ret = tickInterval;
51795
+ }
51796
+ return ret;
51797
+ }
51798
+ /**
51799
+ * If overscroll is pixel or pecentage value, convert it to axis range.
51800
+ *
51801
+ * @private
51802
+ * @param {number | string} overscroll
51803
+ * Overscroll value in axis range, pixels or percentage value.
51804
+ * @return {number}
51805
+ * Overscroll value in axis range.
51806
+ */
51807
+ convertOverscroll(overscroll = 0) {
51808
+ const ordinal = this, axis = ordinal.axis, calculateOverscroll = function (overscrollPercentage) {
51809
+ return pick(ordinal.originalOrdinalRange, defined(axis.dataMax) && defined(axis.dataMin) ?
51810
+ axis.dataMax - axis.dataMin : 0) * overscrollPercentage;
51811
+ };
51812
+ if (isString(overscroll)) {
51813
+ const overscrollValue = parseInt(overscroll, 10);
51814
+ if (/%$/.test(overscroll)) {
51815
+ // If overscroll is percentage
51816
+ return calculateOverscroll(overscrollValue / 100);
51817
+ }
51818
+ if (/px/.test(overscroll)) {
51819
+ // If overscroll is pixels, it is limited to 90% of the axis
51820
+ // length to prevent division by zero
51821
+ const limitedOverscrollValue = Math.min(overscrollValue, axis.len * 0.9), pixelToPercent = limitedOverscrollValue / axis.len;
51822
+ return calculateOverscroll(pixelToPercent / (1 - pixelToPercent));
51823
+ }
51824
+ // If overscroll is a string but not pixels or percentage,
51825
+ // return 0 as no overscroll
51826
+ return 0;
51827
+ }
51828
+ return overscroll;
51829
+ }
51830
+ }
51831
+ OrdinalAxis.Additions = Additions;
51832
+ })(OrdinalAxis || (OrdinalAxis = {}));
51833
+ /* *
51834
+ *
51835
+ * Default Export
51836
+ *
51837
+ * */
51838
+
51839
+ return OrdinalAxis;
51840
+ });
51841
+ _registerModule(_modules, 'Stock/RangeSelector/RangeSelector.js', [_modules['Core/Axis/Axis.js'], _modules['Core/Defaults.js'], _modules['Core/Globals.js'], _modules['Stock/RangeSelector/RangeSelectorComposition.js'], _modules['Core/Renderer/SVG/SVGElement.js'], _modules['Core/Utilities.js'], _modules['Core/Axis/OrdinalAxis.js']], function (Axis, D, H, RangeSelectorComposition, SVGElement, U, OrdinalAxis) {
50714
51842
  /* *
50715
51843
  *
50716
51844
  * (c) 2010-2024 Torstein Honsi
@@ -50786,7 +51914,6 @@
50786
51914
  constructor(chart) {
50787
51915
  this.buttonOptions = RangeSelector.prototype.defaultButtons;
50788
51916
  this.initialButtonGroupWidth = 0;
50789
- this.chart = chart;
50790
51917
  this.init(chart);
50791
51918
  }
50792
51919
  /* *
@@ -50807,7 +51934,7 @@
50807
51934
  clickButton(i, redraw) {
50808
51935
  const rangeSelector = this, chart = rangeSelector.chart, rangeOptions = rangeSelector.buttonOptions[i], baseAxis = chart.xAxis[0], unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || baseAxis || {}, type = rangeOptions.type, dataGrouping = rangeOptions.dataGrouping;
50809
51936
  let dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, newMin, newMax = baseAxis && Math.round(Math.min(baseAxis.max, pick(dataMax, baseAxis.max))), // #1568
50810
- baseXAxisOptions, range = rangeOptions._range, rangeMin, minSetting, rangeSetting, ctx, ytdExtremes, addOffsetMin = true;
51937
+ baseXAxisOptions, range = rangeOptions._range, rangeMin, ctx, ytdExtremes, addOffsetMin = true;
50811
51938
  // Chart has no data, base series is removed
50812
51939
  if (dataMin === null || dataMax === null) {
50813
51940
  return;
@@ -50905,16 +52032,20 @@
50905
52032
  // Update the chart
50906
52033
  if (!baseAxis) {
50907
52034
  // Axis not yet instantiated. Temporarily set min and range
50908
- // options and remove them on chart load (#4317).
52035
+ // options and axes once defined and remove them on
52036
+ // chart load (#4317 & #20529).
50909
52037
  baseXAxisOptions = splat(chart.options.xAxis)[0];
50910
- rangeSetting = baseXAxisOptions.range;
50911
- baseXAxisOptions.range = range;
50912
- minSetting = baseXAxisOptions.min;
50913
- baseXAxisOptions.min = rangeMin;
52038
+ const axisRangeUpdateEvent = addEvent(chart, 'afterGetAxes', function () {
52039
+ const xAxis = chart.xAxis[0];
52040
+ xAxis.range = xAxis.options.range = range;
52041
+ xAxis.min = xAxis.options.min = rangeMin;
52042
+ });
50914
52043
  addEvent(chart, 'load', function resetMinAndRange() {
52044
+ const xAxis = chart.xAxis[0];
50915
52045
  chart.setFixedRange(rangeOptions._range);
50916
- baseXAxisOptions.range = rangeSetting;
50917
- baseXAxisOptions.min = minSetting;
52046
+ xAxis.options.range = baseXAxisOptions.range;
52047
+ xAxis.options.min = baseXAxisOptions.min;
52048
+ axisRangeUpdateEvent(); // Remove event
50918
52049
  });
50919
52050
  }
50920
52051
  else {
@@ -50988,6 +52119,7 @@
50988
52119
  });
50989
52120
  }
50990
52121
  }));
52122
+ this.createElements();
50991
52123
  }
50992
52124
  /**
50993
52125
  * Dynamically update the range selector buttons after a new range has been
@@ -50997,25 +52129,25 @@
50997
52129
  * @function Highcharts.RangeSelector#updateButtonStates
50998
52130
  */
50999
52131
  updateButtonStates() {
51000
- const rangeSelector = this, chart = this.chart, dropdown = this.dropdown, baseAxis = chart.xAxis[0], actualRange = Math.round(baseAxis.max - baseAxis.min), hasNoData = !baseAxis.hasVisibleSeries, day = 24 * 36e5, // A single day in milliseconds
52132
+ const rangeSelector = this, chart = this.chart, dropdown = this.dropdown, dropdownLabel = this.dropdownLabel, baseAxis = chart.xAxis[0], actualRange = Math.round(baseAxis.max - baseAxis.min), hasNoData = !baseAxis.hasVisibleSeries, day = 24 * 36e5, // A single day in milliseconds
51001
52133
  unionExtremes = (chart.scroller &&
51002
- chart.scroller.getUnionExtremes()) || baseAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC), ytdMin = ytdExtremes.min, ytdMax = ytdExtremes.max, selected = rangeSelector.selected, allButtonsEnabled = rangeSelector.options.allButtonsEnabled, buttons = rangeSelector.buttons;
51003
- let selectedExists = isNumber(selected), isSelectedTooGreat = false;
52134
+ chart.scroller.getUnionExtremes()) || baseAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, ytdExtremes = rangeSelector.getYTDExtremes(dataMax, dataMin, chart.time.useUTC), ytdMin = ytdExtremes.min, ytdMax = ytdExtremes.max, selected = rangeSelector.selected, allButtonsEnabled = rangeSelector.options.allButtonsEnabled, buttonStates = new Array(rangeSelector.buttonOptions.length)
52135
+ .fill(0), selectedExists = isNumber(selected), buttons = rangeSelector.buttons;
52136
+ let isSelectedTooGreat = false, selectedIndex = null;
51004
52137
  rangeSelector.buttonOptions.forEach((rangeOptions, i) => {
51005
- const range = rangeOptions._range, type = rangeOptions.type, count = rangeOptions.count || 1, button = buttons[i], offsetRange = rangeOptions._offsetMax -
52138
+ const range = rangeOptions._range, type = rangeOptions.type, count = rangeOptions.count || 1, offsetRange = rangeOptions._offsetMax -
51006
52139
  rangeOptions._offsetMin, isSelected = i === selected,
51007
- // Disable buttons where the range exceeds what is allowed in
52140
+ // Disable buttons where the range exceeds what is allowed i;
51008
52141
  // the current view
51009
52142
  isTooGreatRange = range >
51010
52143
  dataMax - dataMin,
51011
52144
  // Disable buttons where the range is smaller than the minimum
51012
52145
  // range
51013
52146
  isTooSmallRange = range < baseAxis.minRange;
51014
- let state = 0,
51015
52147
  // Do not select the YTD button if not explicitly told so
51016
- isYTDButNotSelected = false,
52148
+ let isYTDButNotSelected = false,
51017
52149
  // Disable the All button if we're already showing all
51018
- isAllButAlreadyShowingAll = false, isSameRange = range === actualRange;
52150
+ isSameRange = range === actualRange;
51019
52151
  if (isSelected && isTooGreatRange) {
51020
52152
  isSelectedTooGreat = true;
51021
52153
  }
@@ -51024,8 +52156,9 @@
51024
52156
  range &&
51025
52157
  actualRange < range) {
51026
52158
  // Handle ordinal ranges
51027
- const positions = baseAxis.ordinal.positions;
51028
- if (positions[positions.length - 1] - positions[0] > range) {
52159
+ const positions = baseAxis.ordinal.positions, prevOrdinalPosition = OrdinalAxis.Additions.findIndexOf(positions, baseAxis.min, true), nextOrdinalPosition = Math.min(OrdinalAxis.Additions.findIndexOf(positions, baseAxis.max, true) + 1, positions.length - 1);
52160
+ if (positions[nextOrdinalPosition] -
52161
+ positions[prevOrdinalPosition] > range) {
51029
52162
  isSameRange = true;
51030
52163
  }
51031
52164
  }
@@ -51045,9 +52178,6 @@
51045
52178
  else if (type === 'all') {
51046
52179
  isSameRange = (baseAxis.max - baseAxis.min >=
51047
52180
  dataMax - dataMin);
51048
- isAllButAlreadyShowingAll = (!isSelected &&
51049
- selectedExists &&
51050
- isSameRange);
51051
52181
  }
51052
52182
  // The new zoom area happens to match the range for a button - mark
51053
52183
  // it selected. This happens when scrolling across an ordinal gap.
@@ -51057,38 +52187,56 @@
51057
52187
  !(isSelectedTooGreat && type === 'all') &&
51058
52188
  (isTooGreatRange ||
51059
52189
  isTooSmallRange ||
51060
- isAllButAlreadyShowingAll ||
51061
52190
  hasNoData));
51062
52191
  const select = ((isSelectedTooGreat && type === 'all') ||
51063
- (isSelected && isSameRange) ||
51064
- (isSameRange && !selectedExists && !isYTDButNotSelected) ||
52192
+ (isYTDButNotSelected ? false : isSameRange) ||
51065
52193
  (isSelected && rangeSelector.frozenStates));
51066
52194
  if (disable) {
51067
- state = 3;
52195
+ buttonStates[i] = 3;
51068
52196
  }
51069
52197
  else if (select) {
51070
- selectedExists = true; // Only one button can be selected
51071
- state = 2;
52198
+ if (!selectedExists || i === selected) {
52199
+ selectedIndex = i;
52200
+ }
51072
52201
  }
51073
- // If state has changed, update the button
52202
+ });
52203
+ if (selectedIndex !== null) {
52204
+ buttonStates[selectedIndex] = 2;
52205
+ rangeSelector.setSelected(selectedIndex);
52206
+ }
52207
+ else {
52208
+ rangeSelector.setSelected();
52209
+ if (dropdownLabel) {
52210
+ dropdownLabel.setState(0);
52211
+ dropdownLabel.attr({
52212
+ text: (defaultOptions.lang.rangeSelectorZoom || '') + ' ▾'
52213
+ });
52214
+ }
52215
+ }
52216
+ for (let i = 0; i < buttonStates.length; i++) {
52217
+ const state = buttonStates[i];
52218
+ const button = buttons[i];
51074
52219
  if (button.state !== state) {
51075
52220
  button.setState(state);
51076
52221
  if (dropdown) {
51077
- dropdown.options[i + 1].disabled = disable;
52222
+ dropdown.options[i + 1].disabled = (state === 3);
51078
52223
  if (state === 2) {
52224
+ if (dropdownLabel) {
52225
+ dropdownLabel.setState(2);
52226
+ dropdownLabel.attr({
52227
+ text: rangeSelector.buttonOptions[i].text + ' ▾'
52228
+ });
52229
+ }
51079
52230
  dropdown.selectedIndex = i + 1;
51080
52231
  }
51081
- }
51082
- // Reset (#9209)
51083
- if (state === 0 && selected === i) {
51084
- rangeSelector.setSelected();
51085
- }
51086
- else if ((state === 2 && !defined(selected)) ||
51087
- isSelectedTooGreat) {
51088
- rangeSelector.setSelected(i);
52232
+ const bbox = dropdownLabel.getBBox();
52233
+ css(dropdown, {
52234
+ width: `${bbox.width}px`,
52235
+ height: `${bbox.height}px`
52236
+ });
51089
52237
  }
51090
52238
  }
51091
- });
52239
+ }
51092
52240
  }
51093
52241
  /**
51094
52242
  * Compute and cache the range for an individual button
@@ -51286,12 +52434,10 @@
51286
52434
  /**
51287
52435
  * @private
51288
52436
  */
51289
- function updateExtremes() {
51290
- const { maxInput, minInput } = rangeSelector, chartAxis = chart.xAxis[0], unionExtremes = (chart.scroller && chart.scroller.getUnionExtremes()) || chartAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax;
52437
+ function updateExtremes(name) {
52438
+ const { maxInput, minInput } = rangeSelector, chartAxis = chart.xAxis[0], unionExtremes = chart.scroller?.getUnionExtremes() || chartAxis, dataMin = unionExtremes.dataMin, dataMax = unionExtremes.dataMax, currentExtreme = chart.xAxis[0].getExtremes()[name];
51291
52439
  let value = rangeSelector.getInputValue(name);
51292
- if (value !== Number(input.getAttribute('data-hc-time-previous')) &&
51293
- isNumber(value)) {
51294
- input.setAttribute('data-hc-time-previous', value);
52440
+ if (isNumber(value) && value !== currentExtreme) {
51295
52441
  // Validate the extremes. If it goes beyond the data min or
51296
52442
  // max, use the actual data extreme (#2438).
51297
52443
  if (isMin && maxInput && isNumber(dataMin)) {
@@ -51388,7 +52534,7 @@
51388
52534
  if (input === H.doc.activeElement) { // Only when focused
51389
52535
  // Update also when no `change` event is triggered, like when
51390
52536
  // clicking inside the SVG (#4710)
51391
- updateExtremes();
52537
+ updateExtremes(name);
51392
52538
  }
51393
52539
  // #10404 - move hide and blur outside focus
51394
52540
  rangeSelector.hideInput(name);
@@ -51400,7 +52546,7 @@
51400
52546
  input.onchange = () => {
51401
52547
  // Update extremes and blur input when clicking date input calendar
51402
52548
  if (!keyDown) {
51403
- updateExtremes();
52549
+ updateExtremes(name);
51404
52550
  rangeSelector.hideInput(name);
51405
52551
  input.blur();
51406
52552
  }
@@ -51408,14 +52554,16 @@
51408
52554
  input.onkeypress = (event) => {
51409
52555
  // IE does not fire onchange on enter
51410
52556
  if (event.keyCode === 13) {
51411
- updateExtremes();
52557
+ updateExtremes(name);
51412
52558
  }
51413
52559
  };
51414
52560
  input.onkeydown = (event) => {
51415
52561
  keyDown = true;
51416
52562
  // Arrow keys
51417
- if (event.keyCode === 38 || event.keyCode === 40) {
51418
- updateExtremes();
52563
+ if (event.key === 'ArrowUp' ||
52564
+ event.key === 'ArrowDown' ||
52565
+ event.key === 'Tab') {
52566
+ updateExtremes(name);
51419
52567
  }
51420
52568
  };
51421
52569
  input.onkeyup = () => {
@@ -51458,6 +52606,42 @@
51458
52606
  min
51459
52607
  };
51460
52608
  }
52609
+ createElements() {
52610
+ const chart = this.chart, renderer = chart.renderer, container = chart.container, chartOptions = chart.options, options = chartOptions.rangeSelector, inputEnabled = options.inputEnabled, inputsZIndex = pick(chartOptions.chart.style?.zIndex, 0) + 1;
52611
+ if (options.enabled === false) {
52612
+ return;
52613
+ }
52614
+ this.group = renderer.g('range-selector-group')
52615
+ .attr({
52616
+ zIndex: 7
52617
+ })
52618
+ .add();
52619
+ this.div = createElement('div', void 0, {
52620
+ position: 'relative',
52621
+ height: 0,
52622
+ zIndex: inputsZIndex
52623
+ });
52624
+ if (this.buttonOptions.length) {
52625
+ this.renderButtons();
52626
+ }
52627
+ // First create a wrapper outside the container in order to make
52628
+ // the inputs work and make export correct
52629
+ if (container.parentNode) {
52630
+ container.parentNode.insertBefore(this.div, container);
52631
+ }
52632
+ if (inputEnabled) {
52633
+ // Create the group to keep the inputs
52634
+ this.inputGroup = renderer.g('input-group').add(this.group);
52635
+ const minElems = this.drawInput('min');
52636
+ this.minDateBox = minElems.dateBox;
52637
+ this.minLabel = minElems.label;
52638
+ this.minInput = minElems.input;
52639
+ const maxElems = this.drawInput('max');
52640
+ this.maxDateBox = maxElems.dateBox;
52641
+ this.maxLabel = maxElems.label;
52642
+ this.maxInput = maxElems.input;
52643
+ }
52644
+ }
51461
52645
  /**
51462
52646
  * Render the range selector including the buttons and the inputs. The first
51463
52647
  * time render is called, the elements are created and positioned. On
@@ -51471,46 +52655,12 @@
51471
52655
  * X axis maximum
51472
52656
  */
51473
52657
  render(min, max) {
51474
- const chart = this.chart, renderer = chart.renderer, container = chart.container, chartOptions = chart.options, options = chartOptions.rangeSelector,
52658
+ const chart = this.chart, chartOptions = chart.options, options = chartOptions.rangeSelector,
51475
52659
  // Place inputs above the container
51476
- inputsZIndex = pick(chartOptions.chart.style &&
51477
- chartOptions.chart.style.zIndex, 0) + 1, inputEnabled = options.inputEnabled, rendered = this.rendered;
52660
+ inputEnabled = options.inputEnabled;
51478
52661
  if (options.enabled === false) {
51479
52662
  return;
51480
52663
  }
51481
- // Create the elements
51482
- if (!rendered) {
51483
- this.group = renderer.g('range-selector-group')
51484
- .attr({
51485
- zIndex: 7
51486
- })
51487
- .add();
51488
- this.div = createElement('div', void 0, {
51489
- position: 'relative',
51490
- height: 0,
51491
- zIndex: inputsZIndex
51492
- });
51493
- if (this.buttonOptions.length) {
51494
- this.renderButtons();
51495
- }
51496
- // First create a wrapper outside the container in order to make
51497
- // the inputs work and make export correct
51498
- if (container.parentNode) {
51499
- container.parentNode.insertBefore(this.div, container);
51500
- }
51501
- if (inputEnabled) {
51502
- // Create the group to keep the inputs
51503
- this.inputGroup = renderer.g('input-group').add(this.group);
51504
- const minElems = this.drawInput('min');
51505
- this.minDateBox = minElems.dateBox;
51506
- this.minLabel = minElems.label;
51507
- this.minInput = minElems.input;
51508
- const maxElems = this.drawInput('max');
51509
- this.maxDateBox = maxElems.dateBox;
51510
- this.maxLabel = maxElems.label;
51511
- this.maxInput = maxElems.input;
51512
- }
51513
- }
51514
52664
  if (inputEnabled) {
51515
52665
  // Set or reset the input values
51516
52666
  this.setInputValue('min', min);
@@ -51542,7 +52692,7 @@
51542
52692
  }
51543
52693
  }
51544
52694
  this.alignElements();
51545
- this.rendered = true;
52695
+ this.updateButtonStates();
51546
52696
  }
51547
52697
  /**
51548
52698
  * Render the range buttons. This only runs the first time, later the
@@ -51566,33 +52716,39 @@
51566
52716
  this.buttonGroup = renderer.g('range-selector-buttons').add(this.group);
51567
52717
  const dropdown = this.dropdown = createElement('select', void 0, {
51568
52718
  position: 'absolute',
51569
- width: '1px',
51570
- height: '1px',
51571
52719
  padding: 0,
51572
52720
  border: 0,
51573
- top: '-9999em',
51574
52721
  cursor: 'pointer',
51575
52722
  opacity: 0.0001
51576
52723
  }, this.div);
52724
+ // Create a label for dropdown select element
52725
+ const userButtonTheme = chart.userOptions.rangeSelector?.buttonTheme;
52726
+ this.dropdownLabel = renderer.button('', 0, 0, () => { }, merge(buttonTheme, {
52727
+ 'stroke-width': pick(buttonTheme['stroke-width'], 0),
52728
+ width: 'auto',
52729
+ paddingLeft: pick(options.buttonTheme.paddingLeft, userButtonTheme?.padding, 8),
52730
+ paddingRight: pick(options.buttonTheme.paddingRight, userButtonTheme?.padding, 8)
52731
+ }), states && states.hover, states && states.select, states && states.disabled)
52732
+ .hide()
52733
+ .add(this.group);
51577
52734
  // Prevent page zoom on iPhone
51578
52735
  addEvent(dropdown, 'touchstart', () => {
51579
52736
  dropdown.style.fontSize = '16px';
51580
52737
  });
51581
52738
  // Forward events from select to button
51582
- [
51583
- [H.isMS ? 'mouseover' : 'mouseenter'],
51584
- [H.isMS ? 'mouseout' : 'mouseleave'],
51585
- ['change', 'click']
51586
- ].forEach(([from, to]) => {
51587
- addEvent(dropdown, from, () => {
51588
- const button = buttons[this.currentButtonIndex()];
51589
- if (button) {
51590
- fireEvent(button.element, to || from);
51591
- }
51592
- });
52739
+ const mouseOver = H.isMS ? 'mouseover' : 'mouseenter', mouseOut = H.isMS ? 'mouseout' : 'mouseleave';
52740
+ addEvent(dropdown, mouseOver, () => {
52741
+ fireEvent(this.dropdownLabel.element, mouseOver);
52742
+ });
52743
+ addEvent(dropdown, mouseOut, () => {
52744
+ fireEvent(this.dropdownLabel.element, mouseOut);
52745
+ });
52746
+ addEvent(dropdown, 'change', () => {
52747
+ const button = this.buttons[dropdown.selectedIndex - 1];
52748
+ fireEvent(button.element, 'click');
51593
52749
  });
51594
52750
  this.zoomText = renderer
51595
- .label((lang && lang.rangeSelectorZoom) || '', 0)
52751
+ .label(lang.rangeSelectorZoom || '', 0)
51596
52752
  .attr({
51597
52753
  padding: options.buttonTheme.padding,
51598
52754
  height: options.buttonTheme.height,
@@ -51684,10 +52840,13 @@
51684
52840
  this.initialButtonGroupWidth = width;
51685
52841
  }
51686
52842
  plotLeft -= chart.spacing[3];
51687
- this.updateButtonStates();
51688
52843
  // Detect collision between button group and exporting
51689
52844
  const xOffsetForExportButton = getXOffsetForExportButton(buttonGroup, buttonPosition);
51690
52845
  this.alignButtonGroup(xOffsetForExportButton);
52846
+ if (this.buttonGroup?.translateY) {
52847
+ this.dropdownLabel
52848
+ .attr({ y: this.buttonGroup.translateY });
52849
+ }
51691
52850
  // Skip animation
51692
52851
  group.placed = buttonGroup.placed = chart.hasLoaded;
51693
52852
  }
@@ -51857,7 +53016,7 @@
51857
53016
  return buttonWidth;
51858
53017
  };
51859
53018
  const groupsOverlap = (buttonGroupWidth) => {
51860
- if (inputGroup && buttonGroup) {
53019
+ if (inputGroup?.alignOptions && buttonGroup) {
51861
53020
  const inputGroupX = (inputGroup.alignAttr.translateX +
51862
53021
  inputGroup.alignOptions.x -
51863
53022
  xOffsetForExportButton +
@@ -51865,7 +53024,7 @@
51865
53024
  inputGroup.getBBox().x +
51866
53025
  // 2px padding to not overlap input and label
51867
53026
  2);
51868
- const inputGroupWidth = inputGroup.alignOptions.width;
53027
+ const inputGroupWidth = inputGroup.alignOptions.width || 0;
51869
53028
  const buttonGroupX = buttonGroup.alignAttr.translateX +
51870
53029
  buttonGroup.getBBox().x;
51871
53030
  return (buttonGroupX + buttonGroupWidth > inputGroupX) &&
@@ -51889,7 +53048,7 @@
51889
53048
  };
51890
53049
  if (buttonGroup) {
51891
53050
  if (dropdown === 'always') {
51892
- this.collapseButtons(xOffsetForExportButton);
53051
+ this.collapseButtons();
51893
53052
  if (groupsOverlap(maxButtonWidth())) {
51894
53053
  // Move the inputs down if there is still a collision
51895
53054
  // after collapsing the buttons
@@ -51907,7 +53066,7 @@
51907
53066
  // 20 is minimal spacing between elements
51908
53067
  groupsOverlap(this.initialButtonGroupWidth + 20)) {
51909
53068
  if (dropdown === 'responsive') {
51910
- this.collapseButtons(xOffsetForExportButton);
53069
+ this.collapseButtons();
51911
53070
  if (groupsOverlap(maxButtonWidth())) {
51912
53071
  moveInputsDown();
51913
53072
  }
@@ -51922,7 +53081,7 @@
51922
53081
  }
51923
53082
  else if (buttonGroup && dropdown === 'responsive') {
51924
53083
  if (this.initialButtonGroupWidth > chart.plotWidth) {
51925
- this.collapseButtons(xOffsetForExportButton);
53084
+ this.collapseButtons();
51926
53085
  }
51927
53086
  else {
51928
53087
  this.expandButtons();
@@ -51930,54 +53089,20 @@
51930
53089
  }
51931
53090
  }
51932
53091
  /**
51933
- * Collapse the buttons and put the select element on top.
53092
+ * Collapse the buttons and show the select element.
51934
53093
  *
51935
53094
  * @private
51936
53095
  * @function Highcharts.RangeSelector#collapseButtons
51937
53096
  * @param {number} xOffsetForExportButton
51938
53097
  */
51939
- collapseButtons(xOffsetForExportButton) {
51940
- const { buttons, buttonOptions, chart, dropdown, options, zoomText } = this;
51941
- // If the buttons are already collapsed do nothing.
53098
+ collapseButtons() {
53099
+ const { buttons, zoomText } = this;
51942
53100
  if (this.isCollapsed === true) {
51943
53101
  return;
51944
53102
  }
51945
53103
  this.isCollapsed = true;
51946
- const userButtonTheme = (chart.userOptions.rangeSelector &&
51947
- chart.userOptions.rangeSelector.buttonTheme) || {};
51948
- const getAttribs = (text) => ({
51949
- text: text ? `${text} ▾` : '▾',
51950
- width: 'auto',
51951
- paddingLeft: pick(options.buttonTheme.paddingLeft, userButtonTheme.padding, 8),
51952
- paddingRight: pick(options.buttonTheme.paddingRight, userButtonTheme.padding, 8)
51953
- });
51954
- if (zoomText) {
51955
- zoomText.hide();
51956
- }
51957
- let hasActiveButton = false;
51958
- buttonOptions.forEach((rangeOptions, i) => {
51959
- const button = buttons[i];
51960
- if (button.state !== 2) {
51961
- button.hide();
51962
- }
51963
- else {
51964
- button.show();
51965
- button.attr(getAttribs(rangeOptions.text));
51966
- hasActiveButton = true;
51967
- }
51968
- });
51969
- if (!hasActiveButton) {
51970
- if (dropdown) {
51971
- dropdown.selectedIndex = 0;
51972
- }
51973
- buttons[0].show();
51974
- buttons[0].attr(getAttribs(this.zoomText && this.zoomText.textStr));
51975
- }
51976
- const { align } = options.buttonPosition;
51977
- this.positionButtons();
51978
- if (align === 'right' || align === 'center') {
51979
- this.alignButtonGroup(xOffsetForExportButton, buttons[this.currentButtonIndex()].getBBox().width);
51980
- }
53104
+ zoomText.hide();
53105
+ buttons.forEach((button) => void button.hide());
51981
53106
  this.showDropdown();
51982
53107
  }
51983
53108
  /**
@@ -51987,44 +53112,16 @@
51987
53112
  * @function Highcharts.RangeSelector#expandButtons
51988
53113
  */
51989
53114
  expandButtons() {
51990
- const { buttons, buttonOptions, options, zoomText } = this;
51991
- this.hideDropdown();
51992
- // If buttons are already not collapsed, do nothing.
53115
+ const { buttons, zoomText } = this;
51993
53116
  if (this.isCollapsed === false) {
51994
53117
  return;
51995
53118
  }
51996
53119
  this.isCollapsed = false;
51997
- if (zoomText) {
51998
- zoomText.show();
51999
- }
52000
- buttonOptions.forEach((rangeOptions, i) => {
52001
- const button = buttons[i];
52002
- button.show();
52003
- button.attr({
52004
- text: rangeOptions.text,
52005
- width: options.buttonTheme.width || 28,
52006
- paddingLeft: pick(options.buttonTheme.paddingLeft, 'unset'),
52007
- paddingRight: pick(options.buttonTheme.paddingRight, 'unset')
52008
- });
52009
- if (button.state < 2) {
52010
- button.setState(0);
52011
- }
52012
- });
53120
+ this.hideDropdown();
53121
+ zoomText.show();
53122
+ buttons.forEach((button) => void button.show());
52013
53123
  this.positionButtons();
52014
53124
  }
52015
- /**
52016
- * Get the index of the visible button when the buttons are collapsed.
52017
- *
52018
- * @private
52019
- * @function Highcharts.RangeSelector#currentButtonIndex
52020
- */
52021
- currentButtonIndex() {
52022
- const { dropdown } = this;
52023
- if (dropdown && dropdown.selectedIndex > 0) {
52024
- return dropdown.selectedIndex - 1;
52025
- }
52026
- return 0;
52027
- }
52028
53125
  /**
52029
53126
  * Position the select element on top of the button.
52030
53127
  *
@@ -52032,14 +53129,16 @@
52032
53129
  * @function Highcharts.RangeSelector#showDropdown
52033
53130
  */
52034
53131
  showDropdown() {
52035
- const { buttonGroup, buttons, chart, dropdown } = this;
53132
+ const { buttonGroup, chart, dropdownLabel, dropdown } = this;
52036
53133
  if (buttonGroup && dropdown) {
52037
- const { translateX = 0, translateY = 0 } = buttonGroup, bBox = buttons[this.currentButtonIndex()].getBBox();
53134
+ const { translateX = 0, translateY = 0 } = buttonGroup, left = chart.plotLeft + translateX, top = translateY;
53135
+ dropdownLabel
53136
+ .attr({ x: left, y: top })
53137
+ .show();
52038
53138
  css(dropdown, {
52039
- left: (chart.plotLeft + translateX) + 'px',
52040
- top: (translateY + 0.5) + 'px',
52041
- width: bBox.width + 'px',
52042
- height: bBox.height + 'px'
53139
+ left: left + 'px',
53140
+ top: top + 'px',
53141
+ visibility: 'inherit'
52043
53142
  });
52044
53143
  this.hasVisibleDropdown = true;
52045
53144
  }
@@ -52051,8 +53150,9 @@
52051
53150
  hideDropdown() {
52052
53151
  const { dropdown } = this;
52053
53152
  if (dropdown) {
53153
+ this.dropdownLabel.hide();
52054
53154
  css(dropdown, {
52055
- top: '-9999em',
53155
+ visibility: 'hidden',
52056
53156
  width: '1px',
52057
53157
  height: '1px'
52058
53158
  });
@@ -52107,12 +53207,14 @@
52107
53207
  * @function Highcharts.RangeSelector#update
52108
53208
  * @param {Highcharts.RangeSelectorOptions} options
52109
53209
  */
52110
- update(options) {
53210
+ update(options, redraw = true) {
52111
53211
  const chart = this.chart;
52112
53212
  merge(true, chart.options.rangeSelector, options);
52113
53213
  this.destroy();
52114
53214
  this.init(chart);
52115
- this.render();
53215
+ if (redraw) {
53216
+ this.render();
53217
+ }
52116
53218
  }
52117
53219
  /**
52118
53220
  * Destroys allocated elements.
@@ -54527,7 +55629,7 @@
54527
55629
  const { composed, noop } = H;
54528
55630
  const { parse: color } = Color;
54529
55631
  const { column: ColumnSeries } = SeriesRegistry.seriesTypes;
54530
- const { addEvent, clamp, defined, extend, find, isNumber, isObject, merge, pick, pushUnique, relativeLength } = U;
55632
+ const { addEvent, clamp, crisp, defined, extend, find, isNumber, isObject, merge, pick, pushUnique, relativeLength } = U;
54531
55633
  /* *
54532
55634
  *
54533
55635
  * Functions
@@ -54674,7 +55776,7 @@
54674
55776
  translatePoint(point) {
54675
55777
  const xAxis = this.xAxis, yAxis = this.yAxis, metrics = this.columnMetrics, options = this.options, minPointLength = options.minPointLength || 0, oldColWidth = (point.shapeArgs && point.shapeArgs.width || 0) / 2, seriesXOffset = this.pointXOffset = metrics.offset, posX = pick(point.x2, point.x + (point.len || 0)), borderRadius = options.borderRadius, plotTop = this.chart.plotTop, plotLeft = this.chart.plotLeft;
54676
55778
  let plotX = point.plotX, plotX2 = xAxis.translate(posX, 0, 0, 0, 1);
54677
- const length = Math.abs(plotX2 - plotX), inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1), crisper = borderWidth % 2 / 2;
55779
+ const length = Math.abs(plotX2 - plotX), inverted = this.chart.inverted, borderWidth = pick(options.borderWidth, 1);
54678
55780
  let widthDifference, partialFill, yOffset = metrics.offset, pointHeight = Math.round(metrics.width), dlLeft, dlRight, dlWidth, clipRectWidth;
54679
55781
  if (minPointLength) {
54680
55782
  widthDifference = minPointLength - length;
@@ -54697,13 +55799,13 @@
54697
55799
  yAxis.categories) {
54698
55800
  point.plotY = yAxis.translate(point.y, 0, 1, 0, 1, options.pointPlacement);
54699
55801
  }
54700
- const x = Math.floor(Math.min(plotX, plotX2)) + crisper, x2 = Math.floor(Math.max(plotX, plotX2)) + crisper, width = x2 - x;
55802
+ const x = crisp(Math.min(plotX, plotX2), borderWidth), x2 = crisp(Math.max(plotX, plotX2), borderWidth), width = x2 - x;
54701
55803
  const r = Math.min(relativeLength((typeof borderRadius === 'object' ?
54702
55804
  borderRadius.radius :
54703
55805
  borderRadius || 0), pointHeight), Math.min(width, pointHeight) / 2);
54704
55806
  const shapeArgs = {
54705
55807
  x,
54706
- y: Math.floor(point.plotY + yOffset) + crisper,
55808
+ y: crisp((point.plotY || 0) + yOffset, borderWidth),
54707
55809
  width,
54708
55810
  height: pointHeight,
54709
55811
  r
@@ -56147,7 +57249,7 @@
56147
57249
  const linePath = axis.getLinePath(lineWidth), startPoint = linePath[0], endPoint = linePath[1],
56148
57250
  // Negate distance if top or left axis
56149
57251
  // Subtract 1px to draw the line at the end of the tick
56150
- tickLength = (axis.tickSize('tick') || [1])[0], distance = (tickLength - 1) * ((axis.side === GridAxisSide.top ||
57252
+ tickLength = (axis.tickSize('tick') || [1])[0], distance = tickLength * ((axis.side === GridAxisSide.top ||
56151
57253
  axis.side === GridAxisSide.left) ? -1 : 1);
56152
57254
  // If axis is horizontal, reposition line path vertically
56153
57255
  if (startPoint[0] === 'M' && endPoint[0] === 'L') {