apexcharts 8.2.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/README.md +7 -7
  2. package/dist/apexcharts.common.js +2 -2
  3. package/dist/apexcharts.core.js +271 -173
  4. package/dist/apexcharts.core.min.js +2 -2
  5. package/dist/apexcharts.css +35 -0
  6. package/dist/apexcharts.esm.js +1722 -1527
  7. package/dist/apexcharts.full.js +1459 -1075
  8. package/dist/apexcharts.full.min.js +2 -2
  9. package/dist/apexcharts.js +994 -715
  10. package/dist/apexcharts.min.js +2 -2
  11. package/dist/apexcharts.ssr.common.js +2 -2
  12. package/dist/apexcharts.ssr.esm.js +994 -715
  13. package/dist/area.common.js +2 -2
  14. package/dist/area.esm.js +91 -40
  15. package/dist/bar.common.js +2 -2
  16. package/dist/bar.esm.js +433 -394
  17. package/dist/bar.js +2 -2
  18. package/dist/boxPlot.common.js +2 -2
  19. package/dist/boxPlot.esm.js +364 -322
  20. package/dist/bubble.common.js +2 -2
  21. package/dist/bubble.esm.js +91 -40
  22. package/dist/candlestick.common.js +2 -2
  23. package/dist/candlestick.esm.js +364 -322
  24. package/dist/candlestick.js +2 -2
  25. package/dist/column.common.js +2 -2
  26. package/dist/column.esm.js +433 -394
  27. package/dist/core.common.js +2 -2
  28. package/dist/core.esm.js +271 -173
  29. package/dist/donut.common.js +1 -1
  30. package/dist/donut.esm.js +1 -1
  31. package/dist/dumbbell.common.js +2 -2
  32. package/dist/dumbbell.esm.js +433 -394
  33. package/dist/features/all.common.js +2 -2
  34. package/dist/features/all.esm.js +250 -187
  35. package/dist/features/annotations.common.js +1 -1
  36. package/dist/features/annotations.esm.js +1 -1
  37. package/dist/features/annotations.js +1 -1
  38. package/dist/features/context-menu.common.js +1 -1
  39. package/dist/features/context-menu.esm.js +1 -1
  40. package/dist/features/context-menu.js +1 -1
  41. package/dist/features/drilldown.common.js +2 -2
  42. package/dist/features/drilldown.esm.js +4 -2
  43. package/dist/features/drilldown.js +2 -2
  44. package/dist/features/dumbbell.common.js +1 -1
  45. package/dist/features/dumbbell.esm.js +1 -1
  46. package/dist/features/dumbbell.js +1 -1
  47. package/dist/features/exports.common.js +1 -1
  48. package/dist/features/exports.esm.js +1 -1
  49. package/dist/features/exports.js +1 -1
  50. package/dist/features/facet.common.js +1 -1
  51. package/dist/features/facet.esm.js +1 -1
  52. package/dist/features/facet.js +1 -1
  53. package/dist/features/highlight-filter.common.js +2 -2
  54. package/dist/features/highlight-filter.esm.js +14 -9
  55. package/dist/features/highlight-filter.js +2 -2
  56. package/dist/features/history.common.js +1 -1
  57. package/dist/features/history.esm.js +1 -1
  58. package/dist/features/history.js +1 -1
  59. package/dist/features/ink.common.js +1 -1
  60. package/dist/features/ink.esm.js +1 -1
  61. package/dist/features/ink.js +1 -1
  62. package/dist/features/keyboard.common.js +2 -2
  63. package/dist/features/keyboard.esm.js +97 -145
  64. package/dist/features/keyboard.js +2 -2
  65. package/dist/features/legend.common.js +2 -2
  66. package/dist/features/legend.esm.js +63 -43
  67. package/dist/features/legend.js +2 -2
  68. package/dist/features/link.common.js +1 -1
  69. package/dist/features/link.esm.js +1 -1
  70. package/dist/features/link.js +1 -1
  71. package/dist/features/marks.common.js +1 -1
  72. package/dist/features/marks.esm.js +1 -1
  73. package/dist/features/marks.js +1 -1
  74. package/dist/features/measure.common.js +1 -1
  75. package/dist/features/measure.esm.js +1 -1
  76. package/dist/features/measure.js +1 -1
  77. package/dist/features/morph.common.js +1 -1
  78. package/dist/features/morph.esm.js +1 -1
  79. package/dist/features/morph.js +1 -1
  80. package/dist/features/perspectives.common.js +1 -1
  81. package/dist/features/perspectives.esm.js +1 -1
  82. package/dist/features/perspectives.js +1 -1
  83. package/dist/features/raincloud.common.js +1 -1
  84. package/dist/features/raincloud.esm.js +1 -1
  85. package/dist/features/raincloud.js +1 -1
  86. package/dist/features/renderer-canvas.common.js +2 -2
  87. package/dist/features/renderer-canvas.esm.js +2 -1
  88. package/dist/features/renderer-canvas.js +2 -2
  89. package/dist/features/stats.common.js +1 -1
  90. package/dist/features/stats.esm.js +1 -1
  91. package/dist/features/stats.js +1 -1
  92. package/dist/features/storyboard.common.js +1 -1
  93. package/dist/features/storyboard.esm.js +1 -1
  94. package/dist/features/storyboard.js +1 -1
  95. package/dist/features/streamgraph.common.js +2 -2
  96. package/dist/features/streamgraph.esm.js +3 -2
  97. package/dist/features/streamgraph.js +2 -2
  98. package/dist/features/toolbar.common.js +2 -2
  99. package/dist/features/toolbar.esm.js +92 -2
  100. package/dist/features/toolbar.js +2 -2
  101. package/dist/features/trellis.common.js +2 -2
  102. package/dist/features/trellis.esm.js +83 -47
  103. package/dist/features/trellis.js +2 -2
  104. package/dist/features/waterfall.common.js +1 -1
  105. package/dist/features/waterfall.esm.js +1 -1
  106. package/dist/features/waterfall.js +1 -1
  107. package/dist/features/weave.common.js +1 -1
  108. package/dist/features/weave.esm.js +1 -1
  109. package/dist/features/weave.js +1 -1
  110. package/dist/full.common.js +2 -2
  111. package/dist/full.esm.js +950 -795
  112. package/dist/heatmap.common.js +2 -2
  113. package/dist/heatmap.esm.js +3 -17
  114. package/dist/heatmap.js +2 -2
  115. package/dist/histogram.common.js +2 -2
  116. package/dist/histogram.esm.js +433 -394
  117. package/dist/icicle.common.js +2 -2
  118. package/dist/icicle.esm.js +54 -38
  119. package/dist/icicle.js +2 -2
  120. package/dist/line.common.js +2 -2
  121. package/dist/line.esm.js +91 -40
  122. package/dist/line.js +2 -2
  123. package/dist/locales/en.json +2 -1
  124. package/dist/locales/ro.json +3 -2
  125. package/dist/pictograms.common.js +1 -1
  126. package/dist/pictograms.esm.js +1 -1
  127. package/dist/pictograms.js +1 -1
  128. package/dist/pie.common.js +1 -1
  129. package/dist/pie.esm.js +1 -1
  130. package/dist/pie.js +1 -1
  131. package/dist/polarArea.common.js +1 -1
  132. package/dist/polarArea.esm.js +1 -1
  133. package/dist/radar.common.js +2 -2
  134. package/dist/radar.esm.js +5 -4
  135. package/dist/radar.js +2 -2
  136. package/dist/radialBar.common.js +1 -1
  137. package/dist/radialBar.esm.js +1 -1
  138. package/dist/radialBar.js +1 -1
  139. package/dist/raincloud.common.js +2 -2
  140. package/dist/raincloud.esm.js +72 -26
  141. package/dist/rangeArea.common.js +2 -2
  142. package/dist/rangeArea.esm.js +91 -40
  143. package/dist/rangeBar.common.js +2 -2
  144. package/dist/rangeBar.esm.js +433 -394
  145. package/dist/scatter.common.js +2 -2
  146. package/dist/scatter.esm.js +91 -40
  147. package/dist/streamgraph.common.js +2 -2
  148. package/dist/streamgraph.esm.js +93 -41
  149. package/dist/sunburst.common.js +2 -2
  150. package/dist/sunburst.esm.js +103 -93
  151. package/dist/sunburst.js +2 -2
  152. package/dist/treemap.common.js +2 -2
  153. package/dist/treemap.esm.js +105 -86
  154. package/dist/treemap.js +2 -2
  155. package/dist/unit-shapes.common.js +1 -1
  156. package/dist/unit-shapes.esm.js +1 -1
  157. package/dist/unit-shapes.js +1 -1
  158. package/dist/unit.common.js +2 -2
  159. package/dist/unit.esm.js +280 -202
  160. package/dist/unit.js +2 -2
  161. package/dist/violin.common.js +2 -2
  162. package/dist/violin.esm.js +72 -26
  163. package/dist/violin.js +2 -2
  164. package/dist/waterfall.common.js +2 -2
  165. package/dist/waterfall.esm.js +432 -393
  166. package/package.json +1 -1
  167. package/src/apexcharts.js +13 -6
  168. package/src/assets/apexcharts.css +35 -0
  169. package/src/charts/Bar.js +62 -55
  170. package/src/charts/BarStacked.js +80 -88
  171. package/src/charts/BoxCandleStick.js +28 -31
  172. package/src/charts/Icicle.js +37 -37
  173. package/src/charts/Line.js +118 -42
  174. package/src/charts/Radar.js +5 -7
  175. package/src/charts/RangeBar.js +47 -43
  176. package/src/charts/Sunburst.js +101 -98
  177. package/src/charts/Treemap.js +108 -66
  178. package/src/charts/Unit.js +368 -250
  179. package/src/charts/Violin.js +48 -30
  180. package/src/charts/common/Breadcrumb.js +2 -2
  181. package/src/charts/common/Hierarchy.js +32 -11
  182. package/src/charts/common/Jitter.js +32 -7
  183. package/src/charts/common/bar/DataLabels.js +76 -81
  184. package/src/charts/common/bar/Helpers.js +43 -7
  185. package/src/charts/common/line/Helpers.js +12 -15
  186. package/src/charts/common/partition/NodeTooltip.js +8 -1
  187. package/src/charts/common/partition/Partition.js +33 -1
  188. package/src/charts/common/treemap/Helpers.js +3 -11
  189. package/src/locales/en.json +2 -1
  190. package/src/locales/ro.json +3 -2
  191. package/src/modules/Core.js +4 -0
  192. package/src/modules/CoreUtils.js +18 -42
  193. package/src/modules/Data.js +23 -24
  194. package/src/modules/DataLabels.js +6 -6
  195. package/src/modules/Graphics.js +62 -49
  196. package/src/modules/Markers.js +3 -1
  197. package/src/modules/Range.js +44 -29
  198. package/src/modules/RendererController.js +17 -3
  199. package/src/modules/Scales.js +32 -9
  200. package/src/modules/Series.js +39 -18
  201. package/src/modules/Theme.js +1 -1
  202. package/src/modules/ZoomPanSelection.js +119 -2
  203. package/src/modules/accessibility/KeyboardNavigation.js +114 -186
  204. package/src/modules/animations/LengthTransition.js +22 -2
  205. package/src/modules/drilldown/Breadcrumb.js +5 -2
  206. package/src/modules/helpers/Destroy.js +1 -1
  207. package/src/modules/highlightFilter/HighlightFilter.js +8 -9
  208. package/src/modules/highlightFilter/TreemapPart.js +2 -2
  209. package/src/modules/legend/HeatmapGradientLegend.js +76 -45
  210. package/src/modules/legend/Helpers.js +2 -0
  211. package/src/modules/legend/Legend.js +11 -12
  212. package/src/modules/settings/Options.js +7 -0
  213. package/src/modules/streamgraph/StreamLabels.js +1 -0
  214. package/src/modules/tooltip/Tooltip.js +20 -4
  215. package/src/modules/tooltip/Utils.js +8 -0
  216. package/src/modules/trellis/Trellis.js +6 -0
  217. package/src/modules/trellis/TrellisChrome.js +18 -7
  218. package/src/modules/trellis/TrellisSync.js +2 -0
  219. package/src/renderers/canvas/CanvasGraphics.js +1 -0
  220. package/src/ssr/DOMShim.js +10 -0
  221. package/src/types/internal.d.ts +9 -3
  222. package/types/apexcharts.d.ts +31 -12
@@ -63,8 +63,9 @@ export default class Series {
63
63
  * @param {string} seriesName
64
64
  */
65
65
  isSeriesHidden(seriesName) {
66
- const targetElement = this.getSeriesByName(seriesName)
67
- const el = /** @type {Element} */ (targetElement)
66
+ const el = this.getSeriesByName(seriesName)
67
+ // An unknown name (or a type that draws no series group) is a no-op.
68
+ if (!el) return { isHidden: false, realIndex: -1 }
68
69
  const realIndex = parseInt(el.getAttribute('data:realIndex') ?? '0', 10)
69
70
  // The collapse is recorded per index for every type; the class only on
70
71
  // the types that draw a series group for it. A pie, donut or polarArea
@@ -295,11 +296,11 @@ export default class Series {
295
296
  * @param {string} seriesName
296
297
  */
297
298
  toggleSeries(seriesName) {
298
- const isSeriesHidden = this.isSeriesHidden(seriesName)
299
+ const { isHidden, realIndex } = this.isSeriesHidden(seriesName)
299
300
 
300
- this._toggleDataSeries?.(isSeriesHidden.realIndex, isSeriesHidden.isHidden)
301
+ if (realIndex > -1) this._toggleDataSeries?.(realIndex, isHidden)
301
302
 
302
- return isSeriesHidden.isHidden
303
+ return isHidden
303
304
  }
304
305
 
305
306
  /**
@@ -319,7 +320,7 @@ export default class Series {
319
320
  hideSeries(seriesName) {
320
321
  const isSeriesHidden = this.isSeriesHidden(seriesName)
321
322
 
322
- if (!isSeriesHidden.isHidden) {
323
+ if (!isSeriesHidden.isHidden && isSeriesHidden.realIndex > -1) {
323
324
  this._toggleDataSeries?.(isSeriesHidden.realIndex, false)
324
325
  }
325
326
  }
@@ -409,10 +410,14 @@ export default class Series {
409
410
  * @param {any[]} series
410
411
  */
411
412
  emptyCollapsedSeries(series) {
412
- const w = this.w
413
+ const gl = this.w.globals
413
414
  if (!Array.isArray(series)) return series
414
415
  for (let i = 0; i < series.length; i++) {
415
- if (w.globals.collapsedSeriesIndices.indexOf(i) > -1) {
416
+ // A series hidden on a showAlways y axis sits on the ancillary list.
417
+ if (
418
+ gl.collapsedSeriesIndices.includes(i) ||
419
+ gl.ancillaryCollapsedSeriesIndices.includes(i)
420
+ ) {
416
421
  // Axis charts carry {name, data}; non-axis charts (pie / donut / unit)
417
422
  // carry a bare numeric value. Empty each in its own shape: setting
418
423
  // `.data` on a number throws ("Cannot create property 'data' on number"),
@@ -656,8 +661,10 @@ export default class Series {
656
661
  */
657
662
  highlightRangeInSeries(rangeIndex, action) {
658
663
  const w = this.w
664
+ // a treemap's gradient legend draws range bands too
665
+ const t = w.config.chart.type === 'treemap' ? 'treemap' : 'heatmap'
659
666
  const allHeatMapElements = w.dom.baseEl.getElementsByClassName(
660
- 'apexcharts-heatmap-rect',
667
+ `apexcharts-${t}-rect`,
661
668
  )
662
669
 
663
670
  /**
@@ -677,17 +684,24 @@ export default class Series {
677
684
  return
678
685
  }
679
686
 
680
- const ranges = w.config.plotOptions.heatmap.colorScale.ranges
687
+ const ranges = w.config.plotOptions[t].colorScale.ranges
681
688
  const range = ranges && ranges[rangeIndex]
682
689
  if (!range) return
683
690
 
684
691
  toggleAllInactive('add')
685
692
  for (let i = 0; i < allHeatMapElements.length; i++) {
686
- const val = Number(allHeatMapElements[i].getAttribute('val'))
693
+ const el = allHeatMapElements[i]
694
+ // treemap tiles carry no val; they are coloured by series[i][j]
695
+ const val = Number(
696
+ el.getAttribute('val') ??
697
+ w.seriesData.series[/** @type {any} */ (el.getAttribute('i'))]?.[
698
+ /** @type {any} */ (el.getAttribute('j'))
699
+ ],
700
+ )
687
701
  // Match the inclusive bounds used by determineColor (treemap/Helpers.js)
688
702
  // so the same cells that were colored by this range get highlighted.
689
703
  if (val >= range.from && val <= range.to) {
690
- allHeatMapElements[i].classList.remove(this.legendInactiveClass)
704
+ el.classList.remove(this.legendInactiveClass)
691
705
  }
692
706
  }
693
707
  }
@@ -711,10 +725,7 @@ export default class Series {
711
725
  return (
712
726
  chartTypes.length === 0 ||
713
727
  (chartTypes.length &&
714
- chartTypes.indexOf(
715
- /** @type {Record<string,any>} */ (w.config.series[index])
716
- .type,
717
- ) > -1)
728
+ chartTypes.indexOf(s.type || w.config.chart.type) > -1)
718
729
  )
719
730
  }
720
731
  return true
@@ -765,7 +776,7 @@ export default class Series {
765
776
  if (
766
777
  w.globals.comboCharts &&
767
778
  chartTypes.length &&
768
- chartTypes.indexOf(s.type) === -1
779
+ chartTypes.indexOf(s.type || w.config.chart.type) === -1
769
780
  ) {
770
781
  return
771
782
  }
@@ -786,7 +797,9 @@ export default class Series {
786
797
  if (w.globals.comboCharts) {
787
798
  return this.w.config.series
788
799
  .map((/** @type {any} */ s, /** @type {number} */ i) => {
789
- return s.type === 'bar' || s.type === 'column' ? i : -1
800
+ // An untyped series draws as chart.type.
801
+ const t = s.type || w.config.chart.type
802
+ return t === 'bar' || t === 'column' ? i : -1
790
803
  })
791
804
  .filter((/** @type {number} */ i) => {
792
805
  return i !== -1
@@ -892,6 +905,13 @@ export default class Series {
892
905
  ((type === 'line' || type === 'area') &&
893
906
  paths[j].getAttribute('d')) ||
894
907
  paths[j].getAttribute('pathTo')
908
+ // A violin's box lane shares its body's datum key: ride on the
909
+ // body's entry so the keyed join stays one path per datum.
910
+ if (paths[j].classList.contains('apexcharts-raincloud-box')) {
911
+ const body = dArr.paths[dArr.paths.length - 1]
912
+ if (body) (body.box ||= []).push(d)
913
+ continue
914
+ }
895
915
  // Datum key + fill stamped by the bar renderer: the key lets the
896
916
  // next render match survivors by identity (not position) and detect
897
917
  // exited datums; the fill paints their exit ghosts.
@@ -935,6 +955,7 @@ export default class Series {
935
955
  'candlestick',
936
956
  'boxPlot',
937
957
  'radar',
958
+ 'violin',
938
959
  ]
939
960
  chartTypes.forEach((type) => {
940
961
  const paths = getPaths(type)
@@ -406,7 +406,7 @@ export default class Theme {
406
406
  c
407
407
  ].colors =
408
408
  w.config[c].colors === undefined
409
- ? this.isColorFn
409
+ ? this.isColorFn && w.config.colors
410
410
  ? w.config.colors.slice()
411
411
  : defaultColors
412
412
  : w.config[c].colors.slice()
@@ -5,6 +5,7 @@ import Toolbar from './Toolbar'
5
5
  import AxisMapping from './AxisMapping'
6
6
  import TooltipUtils from './tooltip/Utils'
7
7
  import { Box } from '../svg/index'
8
+ import { BrowserAPIs } from '../ssr/BrowserAPIs.js'
8
9
 
9
10
  // Wheel-zoom feel: scrolling this many deltaY pixels doubles (or halves) the
10
11
  // visible x-window. 240px is about two discrete wheel notches per 2x zoom
@@ -381,6 +382,67 @@ export default class ZoomPanSelection extends Toolbar {
381
382
  return this._incidentalZoomEnabled(zoom && zoom.allowMouseWheelZoom)
382
383
  }
383
384
 
385
+ /** An explicit `true` zooms on every wheel; 'auto' needs Ctrl/Cmd. */
386
+ _wheelZoomGreedy() {
387
+ return this.w.config.chart.zoom.allowMouseWheelZoom === true
388
+ }
389
+
390
+ /**
391
+ * Tell a viewer whose bare wheel just scrolled past the chart how to zoom it.
392
+ * Shown over the chart while the scroll goes on and faded out shortly after
393
+ * it stops. Only for a mostly vertical wheel: a sideways trackpad swipe is
394
+ * not someone reaching for zoom.
395
+ *
396
+ * The node lives in elWrap and the timer on w.interact, since a re-render can
397
+ * replace both this instance and the wrapper's contents while it is up.
398
+ *
399
+ * @param {any} e
400
+ */
401
+ _showWheelHint(e) {
402
+ const w = this.w
403
+ if (w.config.chart.zoom.wheelHint === false) return
404
+ if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return
405
+ const wrap = w.dom.elWrap
406
+ if (!wrap) return
407
+
408
+ let el = wrap.querySelector('.apexcharts-wheel-hint')
409
+ if (!el) {
410
+ const win = BrowserAPIs.getWindow()
411
+ const nav = win && win.navigator
412
+ const mac = !!nav && /Mac|iPhone|iPad/.test(nav.platform || nav.userAgent)
413
+ const text = (w.globals.locale.toolbar.wheelZoomHint || '').replace(
414
+ '{key}',
415
+ mac ? '⌘' : 'Ctrl',
416
+ )
417
+ el = BrowserAPIs.createElement('div')
418
+ el.className = 'apexcharts-wheel-hint'
419
+ el.setAttribute('aria-hidden', 'true')
420
+ const label = BrowserAPIs.createElement('span')
421
+ label.textContent = text
422
+ label.style.fontFamily = w.config.chart.fontFamily
423
+ el.appendChild(label)
424
+ wrap.appendChild(el)
425
+ // lay the hidden state out before showing it, so it fades in
426
+ void (/** @type {HTMLElement} */ (el).offsetWidth)
427
+ }
428
+ el.classList.add('apexcharts-wheel-hint-visible')
429
+
430
+ const it = w.interact
431
+ if (it.wheelHintTimer) clearTimeout(it.wheelHintTimer)
432
+ it.wheelHintTimer = setTimeout(() => this._hideWheelHint(), 1200)
433
+ }
434
+
435
+ _hideWheelHint() {
436
+ const w = this.w
437
+ const it = w.interact
438
+ if (it.wheelHintTimer) {
439
+ clearTimeout(it.wheelHintTimer)
440
+ it.wheelHintTimer = null
441
+ }
442
+ const el = w.dom.elWrap?.querySelector('.apexcharts-wheel-hint')
443
+ if (el) el.classList.remove('apexcharts-wheel-hint-visible')
444
+ }
445
+
384
446
  /**
385
447
  * Put keyboard focus on the chart, where the chart is focusable at all.
386
448
  *
@@ -454,10 +516,28 @@ export default class ZoomPanSelection extends Toolbar {
454
516
  * @param {any} e
455
517
  */
456
518
  mouseWheelEvent(e) {
457
- e.preventDefault()
458
-
459
519
  const st = this._wheel()
460
520
 
521
+ // Cooperative wheel ('auto'): a bare wheel belongs to the page, so a
522
+ // dashboard of charts scrolls past them instead of zooming each one it
523
+ // crosses. Ctrl/Cmd + wheel zooms, and so does a trackpad pinch, which
524
+ // browsers deliver as a wheel event with ctrlKey set. Once a zoom gesture
525
+ // is under way it keeps the wheel until it settles, so a trackpad's
526
+ // momentum tail after the key comes up does not spill into a page scroll.
527
+ // An explicit `true` keeps the greedy wheel (every scroll zooms).
528
+ if (
529
+ !this._wheelZoomGreedy() &&
530
+ !e.ctrlKey &&
531
+ !e.metaKey &&
532
+ st.endTimer == null
533
+ ) {
534
+ this._showWheelHint(e)
535
+ return
536
+ }
537
+
538
+ e.preventDefault()
539
+ this._hideWheelHint()
540
+
461
541
  // normalize the delta to pixels (deltaMode 1 = lines, 2 = pages)
462
542
  let dy = e.deltaY
463
543
  if (e.deltaMode === 1) dy *= 33
@@ -1520,6 +1600,43 @@ export default class ZoomPanSelection extends Toolbar {
1520
1600
  this.ctx.events.fireEvent('scrolled', args)
1521
1601
  }
1522
1602
 
1603
+ /**
1604
+ * Pan a zoomed x-window by `fraction` of its width (keyboard Shift+Arrow),
1605
+ * clamped to the data as a drag pan is, and reported as one (`scrolled`).
1606
+ * @param {number} fraction
1607
+ */
1608
+ panBy(fraction) {
1609
+ const w = this.w
1610
+ if (!w.interact.zoomed) return
1611
+ const { min, max } = this._currentXWindow()
1612
+ let d = (max - min) * fraction
1613
+ // a category window moves by whole categories
1614
+ if (w.config.xaxis.convertedCatToNumeric) {
1615
+ d = d > 0 ? Math.ceil(d) : Math.floor(d)
1616
+ }
1617
+ // _clampBounds has none for a rangeBar: stop at the ends of its bars
1618
+ if (w.axisFlags.isRangeBar) {
1619
+ const r = w.rangeData
1620
+ let lo = Infinity
1621
+ let hi = -Infinity
1622
+ r.seriesRangeStart
1623
+ .concat(r.seriesRangeEnd)
1624
+ .flat()
1625
+ .forEach((/** @type {any} */ y) => {
1626
+ if (y != null) {
1627
+ lo = Math.min(lo, y)
1628
+ hi = Math.max(hi, y)
1629
+ }
1630
+ })
1631
+ d =
1632
+ d > 0
1633
+ ? Math.min(d, Math.max(0, hi - max))
1634
+ : Math.max(d, Math.min(0, lo - min))
1635
+ if (!d) return
1636
+ }
1637
+ if (this._applyXRange(min + d, max + d, false)) this._fireScrolled()
1638
+ }
1639
+
1523
1640
  /** @param {number} x @param {number} t */
1524
1641
  _pushSample(x, t) {
1525
1642
  const s = this._m().samples