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.
- package/README.md +7 -7
- package/dist/apexcharts.common.js +2 -2
- package/dist/apexcharts.core.js +271 -173
- package/dist/apexcharts.core.min.js +2 -2
- package/dist/apexcharts.css +35 -0
- package/dist/apexcharts.esm.js +1722 -1527
- package/dist/apexcharts.full.js +1459 -1075
- package/dist/apexcharts.full.min.js +2 -2
- package/dist/apexcharts.js +994 -715
- package/dist/apexcharts.min.js +2 -2
- package/dist/apexcharts.ssr.common.js +2 -2
- package/dist/apexcharts.ssr.esm.js +994 -715
- package/dist/area.common.js +2 -2
- package/dist/area.esm.js +91 -40
- package/dist/bar.common.js +2 -2
- package/dist/bar.esm.js +433 -394
- package/dist/bar.js +2 -2
- package/dist/boxPlot.common.js +2 -2
- package/dist/boxPlot.esm.js +364 -322
- package/dist/bubble.common.js +2 -2
- package/dist/bubble.esm.js +91 -40
- package/dist/candlestick.common.js +2 -2
- package/dist/candlestick.esm.js +364 -322
- package/dist/candlestick.js +2 -2
- package/dist/column.common.js +2 -2
- package/dist/column.esm.js +433 -394
- package/dist/core.common.js +2 -2
- package/dist/core.esm.js +271 -173
- package/dist/donut.common.js +1 -1
- package/dist/donut.esm.js +1 -1
- package/dist/dumbbell.common.js +2 -2
- package/dist/dumbbell.esm.js +433 -394
- package/dist/features/all.common.js +2 -2
- package/dist/features/all.esm.js +250 -187
- package/dist/features/annotations.common.js +1 -1
- package/dist/features/annotations.esm.js +1 -1
- package/dist/features/annotations.js +1 -1
- package/dist/features/context-menu.common.js +1 -1
- package/dist/features/context-menu.esm.js +1 -1
- package/dist/features/context-menu.js +1 -1
- package/dist/features/drilldown.common.js +2 -2
- package/dist/features/drilldown.esm.js +4 -2
- package/dist/features/drilldown.js +2 -2
- package/dist/features/dumbbell.common.js +1 -1
- package/dist/features/dumbbell.esm.js +1 -1
- package/dist/features/dumbbell.js +1 -1
- package/dist/features/exports.common.js +1 -1
- package/dist/features/exports.esm.js +1 -1
- package/dist/features/exports.js +1 -1
- package/dist/features/facet.common.js +1 -1
- package/dist/features/facet.esm.js +1 -1
- package/dist/features/facet.js +1 -1
- package/dist/features/highlight-filter.common.js +2 -2
- package/dist/features/highlight-filter.esm.js +14 -9
- package/dist/features/highlight-filter.js +2 -2
- package/dist/features/history.common.js +1 -1
- package/dist/features/history.esm.js +1 -1
- package/dist/features/history.js +1 -1
- package/dist/features/ink.common.js +1 -1
- package/dist/features/ink.esm.js +1 -1
- package/dist/features/ink.js +1 -1
- package/dist/features/keyboard.common.js +2 -2
- package/dist/features/keyboard.esm.js +97 -145
- package/dist/features/keyboard.js +2 -2
- package/dist/features/legend.common.js +2 -2
- package/dist/features/legend.esm.js +63 -43
- package/dist/features/legend.js +2 -2
- package/dist/features/link.common.js +1 -1
- package/dist/features/link.esm.js +1 -1
- package/dist/features/link.js +1 -1
- package/dist/features/marks.common.js +1 -1
- package/dist/features/marks.esm.js +1 -1
- package/dist/features/marks.js +1 -1
- package/dist/features/measure.common.js +1 -1
- package/dist/features/measure.esm.js +1 -1
- package/dist/features/measure.js +1 -1
- package/dist/features/morph.common.js +1 -1
- package/dist/features/morph.esm.js +1 -1
- package/dist/features/morph.js +1 -1
- package/dist/features/perspectives.common.js +1 -1
- package/dist/features/perspectives.esm.js +1 -1
- package/dist/features/perspectives.js +1 -1
- package/dist/features/raincloud.common.js +1 -1
- package/dist/features/raincloud.esm.js +1 -1
- package/dist/features/raincloud.js +1 -1
- package/dist/features/renderer-canvas.common.js +2 -2
- package/dist/features/renderer-canvas.esm.js +2 -1
- package/dist/features/renderer-canvas.js +2 -2
- package/dist/features/stats.common.js +1 -1
- package/dist/features/stats.esm.js +1 -1
- package/dist/features/stats.js +1 -1
- package/dist/features/storyboard.common.js +1 -1
- package/dist/features/storyboard.esm.js +1 -1
- package/dist/features/storyboard.js +1 -1
- package/dist/features/streamgraph.common.js +2 -2
- package/dist/features/streamgraph.esm.js +3 -2
- package/dist/features/streamgraph.js +2 -2
- package/dist/features/toolbar.common.js +2 -2
- package/dist/features/toolbar.esm.js +92 -2
- package/dist/features/toolbar.js +2 -2
- package/dist/features/trellis.common.js +2 -2
- package/dist/features/trellis.esm.js +83 -47
- package/dist/features/trellis.js +2 -2
- package/dist/features/waterfall.common.js +1 -1
- package/dist/features/waterfall.esm.js +1 -1
- package/dist/features/waterfall.js +1 -1
- package/dist/features/weave.common.js +1 -1
- package/dist/features/weave.esm.js +1 -1
- package/dist/features/weave.js +1 -1
- package/dist/full.common.js +2 -2
- package/dist/full.esm.js +950 -795
- package/dist/heatmap.common.js +2 -2
- package/dist/heatmap.esm.js +3 -17
- package/dist/heatmap.js +2 -2
- package/dist/histogram.common.js +2 -2
- package/dist/histogram.esm.js +433 -394
- package/dist/icicle.common.js +2 -2
- package/dist/icicle.esm.js +54 -38
- package/dist/icicle.js +2 -2
- package/dist/line.common.js +2 -2
- package/dist/line.esm.js +91 -40
- package/dist/line.js +2 -2
- package/dist/locales/en.json +2 -1
- package/dist/locales/ro.json +3 -2
- package/dist/pictograms.common.js +1 -1
- package/dist/pictograms.esm.js +1 -1
- package/dist/pictograms.js +1 -1
- package/dist/pie.common.js +1 -1
- package/dist/pie.esm.js +1 -1
- package/dist/pie.js +1 -1
- package/dist/polarArea.common.js +1 -1
- package/dist/polarArea.esm.js +1 -1
- package/dist/radar.common.js +2 -2
- package/dist/radar.esm.js +5 -4
- package/dist/radar.js +2 -2
- package/dist/radialBar.common.js +1 -1
- package/dist/radialBar.esm.js +1 -1
- package/dist/radialBar.js +1 -1
- package/dist/raincloud.common.js +2 -2
- package/dist/raincloud.esm.js +72 -26
- package/dist/rangeArea.common.js +2 -2
- package/dist/rangeArea.esm.js +91 -40
- package/dist/rangeBar.common.js +2 -2
- package/dist/rangeBar.esm.js +433 -394
- package/dist/scatter.common.js +2 -2
- package/dist/scatter.esm.js +91 -40
- package/dist/streamgraph.common.js +2 -2
- package/dist/streamgraph.esm.js +93 -41
- package/dist/sunburst.common.js +2 -2
- package/dist/sunburst.esm.js +103 -93
- package/dist/sunburst.js +2 -2
- package/dist/treemap.common.js +2 -2
- package/dist/treemap.esm.js +105 -86
- package/dist/treemap.js +2 -2
- package/dist/unit-shapes.common.js +1 -1
- package/dist/unit-shapes.esm.js +1 -1
- package/dist/unit-shapes.js +1 -1
- package/dist/unit.common.js +2 -2
- package/dist/unit.esm.js +280 -202
- package/dist/unit.js +2 -2
- package/dist/violin.common.js +2 -2
- package/dist/violin.esm.js +72 -26
- package/dist/violin.js +2 -2
- package/dist/waterfall.common.js +2 -2
- package/dist/waterfall.esm.js +432 -393
- package/package.json +1 -1
- package/src/apexcharts.js +13 -6
- package/src/assets/apexcharts.css +35 -0
- package/src/charts/Bar.js +62 -55
- package/src/charts/BarStacked.js +80 -88
- package/src/charts/BoxCandleStick.js +28 -31
- package/src/charts/Icicle.js +37 -37
- package/src/charts/Line.js +118 -42
- package/src/charts/Radar.js +5 -7
- package/src/charts/RangeBar.js +47 -43
- package/src/charts/Sunburst.js +101 -98
- package/src/charts/Treemap.js +108 -66
- package/src/charts/Unit.js +368 -250
- package/src/charts/Violin.js +48 -30
- package/src/charts/common/Breadcrumb.js +2 -2
- package/src/charts/common/Hierarchy.js +32 -11
- package/src/charts/common/Jitter.js +32 -7
- package/src/charts/common/bar/DataLabels.js +76 -81
- package/src/charts/common/bar/Helpers.js +43 -7
- package/src/charts/common/line/Helpers.js +12 -15
- package/src/charts/common/partition/NodeTooltip.js +8 -1
- package/src/charts/common/partition/Partition.js +33 -1
- package/src/charts/common/treemap/Helpers.js +3 -11
- package/src/locales/en.json +2 -1
- package/src/locales/ro.json +3 -2
- package/src/modules/Core.js +4 -0
- package/src/modules/CoreUtils.js +18 -42
- package/src/modules/Data.js +23 -24
- package/src/modules/DataLabels.js +6 -6
- package/src/modules/Graphics.js +62 -49
- package/src/modules/Markers.js +3 -1
- package/src/modules/Range.js +44 -29
- package/src/modules/RendererController.js +17 -3
- package/src/modules/Scales.js +32 -9
- package/src/modules/Series.js +39 -18
- package/src/modules/Theme.js +1 -1
- package/src/modules/ZoomPanSelection.js +119 -2
- package/src/modules/accessibility/KeyboardNavigation.js +114 -186
- package/src/modules/animations/LengthTransition.js +22 -2
- package/src/modules/drilldown/Breadcrumb.js +5 -2
- package/src/modules/helpers/Destroy.js +1 -1
- package/src/modules/highlightFilter/HighlightFilter.js +8 -9
- package/src/modules/highlightFilter/TreemapPart.js +2 -2
- package/src/modules/legend/HeatmapGradientLegend.js +76 -45
- package/src/modules/legend/Helpers.js +2 -0
- package/src/modules/legend/Legend.js +11 -12
- package/src/modules/settings/Options.js +7 -0
- package/src/modules/streamgraph/StreamLabels.js +1 -0
- package/src/modules/tooltip/Tooltip.js +20 -4
- package/src/modules/tooltip/Utils.js +8 -0
- package/src/modules/trellis/Trellis.js +6 -0
- package/src/modules/trellis/TrellisChrome.js +18 -7
- package/src/modules/trellis/TrellisSync.js +2 -0
- package/src/renderers/canvas/CanvasGraphics.js +1 -0
- package/src/ssr/DOMShim.js +10 -0
- package/src/types/internal.d.ts +9 -3
- package/types/apexcharts.d.ts +31 -12
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import Graphics from '../Graphics'
|
|
3
3
|
import TooltipUtils from '../tooltip/Utils'
|
|
4
|
-
import Utils from '../../utils/Utils'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* ApexCharts KeyboardNavigation
|
|
@@ -16,7 +15,7 @@ import Utils from '../../utils/Utils'
|
|
|
16
15
|
* heatmap, the row above / below
|
|
17
16
|
* Home: first data point in current series
|
|
18
17
|
* End: last data point in current series
|
|
19
|
-
* Enter / Space: fire markerClick
|
|
18
|
+
* Enter / Space: select the point and fire markerClick, as a click does
|
|
20
19
|
* Escape: exit keyboard nav, return focus to SVG
|
|
21
20
|
*/
|
|
22
21
|
export default class KeyboardNavigation {
|
|
@@ -107,12 +106,27 @@ export default class KeyboardNavigation {
|
|
|
107
106
|
// keyboard-nav tooltip so it doesn't remain stuck on screen while the chart
|
|
108
107
|
// re-renders with a different set of visible series.
|
|
109
108
|
this.ctx.events.addEventListener('legendClick', this._onLegendClick)
|
|
109
|
+
|
|
110
|
+
// An update (a keyboard zoom or pan among them) replaced a focused SVG:
|
|
111
|
+
// focus this one, with the cursor and a dismissed tooltip as they were
|
|
112
|
+
// (destroy), unless focus has gone somewhere else since
|
|
113
|
+
const kept = w.interact.keyNav
|
|
114
|
+
const doc = svgEl.ownerDocument
|
|
115
|
+
w.interact.keyNav = null
|
|
116
|
+
if (kept && (!doc.activeElement || doc.activeElement === doc.body)) {
|
|
117
|
+
;[this.seriesIndex, this.dataPointIndex, , this._tooltipDismissed] = kept
|
|
118
|
+
// Focus alone, without starting nav, if nav was not running
|
|
119
|
+
if (!kept[2]) this.notePointerFocus()
|
|
120
|
+
svgEl.focus({ preventScroll: true })
|
|
121
|
+
}
|
|
110
122
|
}
|
|
111
123
|
|
|
112
124
|
/**
|
|
113
|
-
* Removes all event listeners. Called from chart.destroy()
|
|
125
|
+
* Removes all event listeners. Called from chart.destroy(), and with
|
|
126
|
+
* `updating` when an update is about to replace the SVG.
|
|
127
|
+
* @param {boolean} [updating]
|
|
114
128
|
*/
|
|
115
|
-
destroy() {
|
|
129
|
+
destroy(updating) {
|
|
116
130
|
const w = this.w
|
|
117
131
|
const svgEl = w.dom.Paper && w.dom.Paper.node
|
|
118
132
|
|
|
@@ -126,6 +140,14 @@ export default class KeyboardNavigation {
|
|
|
126
140
|
|
|
127
141
|
if (!svgEl) return
|
|
128
142
|
|
|
143
|
+
if (updating && svgEl.getRootNode?.().activeElement === svgEl) {
|
|
144
|
+
w.interact.keyNav = [
|
|
145
|
+
this.seriesIndex,
|
|
146
|
+
this.dataPointIndex,
|
|
147
|
+
this.active,
|
|
148
|
+
this._tooltipDismissed,
|
|
149
|
+
]
|
|
150
|
+
}
|
|
129
151
|
svgEl.removeEventListener('focus', this._onFocus)
|
|
130
152
|
svgEl.removeEventListener('blur', this._onBlur)
|
|
131
153
|
svgEl.removeEventListener('keydown', this._onKeyDown)
|
|
@@ -192,7 +214,8 @@ export default class KeyboardNavigation {
|
|
|
192
214
|
// If the chart is zoomed, snap the cursor to the first visible data point
|
|
193
215
|
// so the user doesn't start navigating outside the current viewport.
|
|
194
216
|
this._snapToVisibleRange()
|
|
195
|
-
|
|
217
|
+
// An update re-focusing a chart whose tooltip was dismissed (init)
|
|
218
|
+
if (!this._tooltipDismissed) this._showCurrentPoint()
|
|
196
219
|
}
|
|
197
220
|
|
|
198
221
|
_onBlur() {
|
|
@@ -249,20 +272,18 @@ export default class KeyboardNavigation {
|
|
|
249
272
|
break
|
|
250
273
|
case 'Home':
|
|
251
274
|
e.preventDefault()
|
|
252
|
-
this.
|
|
253
|
-
this._skipNullForward()
|
|
275
|
+
this._seek(0, 1)
|
|
254
276
|
this._showCurrentPoint()
|
|
255
277
|
break
|
|
256
278
|
case 'End':
|
|
257
279
|
e.preventDefault()
|
|
258
|
-
this.
|
|
259
|
-
this._skipNullBackward()
|
|
280
|
+
this._seek(this._getDataPointCount(this.seriesIndex) - 1, -1)
|
|
260
281
|
this._showCurrentPoint()
|
|
261
282
|
break
|
|
262
283
|
case 'Enter':
|
|
263
284
|
case ' ':
|
|
264
285
|
e.preventDefault()
|
|
265
|
-
this._fireClick()
|
|
286
|
+
this._fireClick(e)
|
|
266
287
|
break
|
|
267
288
|
case '+':
|
|
268
289
|
case '=':
|
|
@@ -323,28 +344,16 @@ export default class KeyboardNavigation {
|
|
|
323
344
|
}
|
|
324
345
|
|
|
325
346
|
_canPan() {
|
|
326
|
-
//
|
|
327
|
-
|
|
328
|
-
// toolbar's zoomUpdateOptions clamps to data bounds.
|
|
329
|
-
return this._canZoom()
|
|
347
|
+
// Unzoomed, the whole domain is in view: there is nothing to pan to
|
|
348
|
+
return this._canZoom() && this.w.interact.zoomed
|
|
330
349
|
}
|
|
331
350
|
|
|
332
351
|
/**
|
|
333
|
-
* Shift the visible x-range by ~10% in the given direction.
|
|
352
|
+
* Shift the visible x-range by ~10% in the given direction, as a drag pan.
|
|
334
353
|
* @param {number} direction +1 = right, -1 = left
|
|
335
354
|
*/
|
|
336
355
|
_panBy(direction) {
|
|
337
|
-
|
|
338
|
-
if (!toolbar) return
|
|
339
|
-
|
|
340
|
-
const r = toolbar._currentXRange()
|
|
341
|
-
const minX = Number(r.minX)
|
|
342
|
-
const maxX = Number(r.maxX)
|
|
343
|
-
if (!isFinite(minX) || !isFinite(maxX) || minX === maxX) return
|
|
344
|
-
|
|
345
|
-
const span = maxX - minX
|
|
346
|
-
const step = span * 0.1 * direction
|
|
347
|
-
toolbar.zoomUpdateOptions(minX + step, maxX + step)
|
|
356
|
+
this.ctx.zoomPanSelection?.panBy(direction / 10)
|
|
348
357
|
this._announce(direction > 0 ? 'Panned right' : 'Panned left')
|
|
349
358
|
}
|
|
350
359
|
|
|
@@ -365,13 +374,15 @@ export default class KeyboardNavigation {
|
|
|
365
374
|
// so ↑/↓ series switching would show the same content — suppress it.
|
|
366
375
|
// For irregular time series the tooltip falls back to individual mode
|
|
367
376
|
// (isXoverlap returns false), so up/down navigation is meaningful there.
|
|
368
|
-
// A heatmap or treemap tooltip is always one cell's
|
|
369
|
-
// tooltip.shared says (and it defaults to true), so
|
|
370
|
-
// way to another row.
|
|
377
|
+
// A heatmap or treemap tooltip is always one cell's and a radialBar's
|
|
378
|
+
// one ring's, whatever tooltip.shared says (and it defaults to true), so
|
|
379
|
+
// ↑/↓ is the only way to another row. Without a tooltip nothing shows
|
|
380
|
+
// the other series either.
|
|
371
381
|
const ttCtx = this.w.globals.tooltip
|
|
372
382
|
const type = w.config.chart.type
|
|
373
|
-
const perCell =
|
|
374
|
-
|
|
383
|
+
const perCell =
|
|
384
|
+
type === 'heatmap' || type === 'treemap' || type === 'radialBar'
|
|
385
|
+
if (!perCell && ttCtx?.ttItems && ttCtx.tConfig.shared) {
|
|
375
386
|
const j = this.dataPointIndex
|
|
376
387
|
const isActuallyShared =
|
|
377
388
|
ttCtx.tooltipUtil &&
|
|
@@ -413,20 +424,7 @@ export default class KeyboardNavigation {
|
|
|
413
424
|
|
|
414
425
|
if (dPoint !== 0) {
|
|
415
426
|
// Move between data points (←/→)
|
|
416
|
-
|
|
417
|
-
let di = this.dataPointIndex + dPoint
|
|
418
|
-
|
|
419
|
-
if (di < 0) di = wrapAround ? dpCount - 1 : 0
|
|
420
|
-
if (di >= dpCount) di = wrapAround ? 0 : dpCount - 1
|
|
421
|
-
|
|
422
|
-
this.dataPointIndex = di
|
|
423
|
-
|
|
424
|
-
// Skip null values
|
|
425
|
-
if (dPoint > 0) {
|
|
426
|
-
this._skipNullForward()
|
|
427
|
-
} else {
|
|
428
|
-
this._skipNullBackward()
|
|
429
|
-
}
|
|
427
|
+
this._seek(this.dataPointIndex + dPoint, dPoint)
|
|
430
428
|
|
|
431
429
|
// If the chart is zoomed, skip data points outside the visible range
|
|
432
430
|
if (!this._isDataPointVisible(this.seriesIndex, this.dataPointIndex)) {
|
|
@@ -437,40 +435,26 @@ export default class KeyboardNavigation {
|
|
|
437
435
|
this._showCurrentPoint()
|
|
438
436
|
}
|
|
439
437
|
|
|
440
|
-
/**
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
// Non-axis charts (pie, etc.) have flat numeric series — no nulls to skip
|
|
449
|
-
if (!Array.isArray(w.seriesData.series[si])) return
|
|
450
|
-
|
|
451
|
-
while (attempts < dpCount && w.seriesData.series[si][di] === null) {
|
|
452
|
-
di = (di + 1) % dpCount
|
|
453
|
-
attempts++
|
|
454
|
-
}
|
|
455
|
-
this.dataPointIndex = di
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/** Retreat dataPointIndex backward past any nulls */
|
|
459
|
-
_skipNullBackward() {
|
|
438
|
+
/**
|
|
439
|
+
* Land on the first non-null point from `di` going `dir`. Past an edge it
|
|
440
|
+
* wraps only with wrapAround; when no point lies ahead the cursor stays.
|
|
441
|
+
* @param {number} di
|
|
442
|
+
* @param {number} dir
|
|
443
|
+
*/
|
|
444
|
+
_seek(di, dir) {
|
|
460
445
|
const w = this.w
|
|
461
|
-
const
|
|
462
|
-
const
|
|
463
|
-
let
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
446
|
+
const row = w.seriesData.series[this.seriesIndex]
|
|
447
|
+
const n = this._getDataPointCount(this.seriesIndex)
|
|
448
|
+
for (let k = 0; k < n; k++, di += dir) {
|
|
449
|
+
if (w.config.chart.accessibility.keyboard.navigation.wrapAround) {
|
|
450
|
+
di = (di + n) % n
|
|
451
|
+
} else if (di < 0 || di >= n) return
|
|
452
|
+
// Non-axis charts (pie, radialBar) have flat values, no nulls
|
|
453
|
+
if (!Array.isArray(row) || row[di] !== null) {
|
|
454
|
+
this.dataPointIndex = di
|
|
455
|
+
return
|
|
456
|
+
}
|
|
472
457
|
}
|
|
473
|
-
this.dataPointIndex = di
|
|
474
458
|
}
|
|
475
459
|
|
|
476
460
|
// ─── Display ──────────────────────────────────────────────────────────────
|
|
@@ -480,13 +464,15 @@ export default class KeyboardNavigation {
|
|
|
480
464
|
const w = this.w
|
|
481
465
|
const ttCtx = w.globals.tooltip
|
|
482
466
|
|
|
483
|
-
|
|
484
|
-
|
|
467
|
+
// Showing a point again undoes an Escape dismissal
|
|
468
|
+
this._tooltipDismissed = false
|
|
485
469
|
// Keep globals consistent with the rest of the system
|
|
486
470
|
w.interact.capturedSeriesIndex = i
|
|
487
471
|
w.interact.capturedDataPointIndex = j
|
|
488
472
|
|
|
489
473
|
this._applyFocusClass(i, j)
|
|
474
|
+
// No tooltip to read out the point, so the live region names it
|
|
475
|
+
if (!ttCtx?.ttItems) return this._announce(this._buildPointLabel(i, j))
|
|
490
476
|
this._showTooltip(i, j, /** @type {any} */ (ttCtx))
|
|
491
477
|
}
|
|
492
478
|
|
|
@@ -571,10 +557,13 @@ export default class KeyboardNavigation {
|
|
|
571
557
|
tooltipEl.removeAttribute('aria-hidden')
|
|
572
558
|
}
|
|
573
559
|
|
|
574
|
-
if (
|
|
560
|
+
if (
|
|
561
|
+
type === 'pie' ||
|
|
562
|
+
type === 'donut' ||
|
|
563
|
+
type === 'polarArea' ||
|
|
564
|
+
type === 'radialBar'
|
|
565
|
+
) {
|
|
575
566
|
this._showTooltipNonAxis(i, j, ttCtx, tooltipEl)
|
|
576
|
-
} else if (type === 'radialBar') {
|
|
577
|
-
this._showTooltipRadialBar(i, j, ttCtx, tooltipEl)
|
|
578
567
|
} else if (type === 'heatmap' || type === 'treemap') {
|
|
579
568
|
this._showTooltipHeatTree(i, j, ttCtx, tooltipEl, type)
|
|
580
569
|
} else if (this._isBarLikeSeries(i)) {
|
|
@@ -1130,19 +1119,17 @@ export default class KeyboardNavigation {
|
|
|
1130
1119
|
}
|
|
1131
1120
|
|
|
1132
1121
|
/**
|
|
1133
|
-
* pie / donut / polarArea
|
|
1122
|
+
* pie / donut / polarArea (a slice per point, i is 0) and radialBar (a ring
|
|
1123
|
+
* per series, j is 0)
|
|
1134
1124
|
* @param {number} i
|
|
1135
1125
|
* @param {number} j
|
|
1136
1126
|
* @param {import('../tooltip/Tooltip').default} ttCtx
|
|
1137
1127
|
* @param {HTMLElement} tooltipEl
|
|
1138
1128
|
*/
|
|
1139
1129
|
_showTooltipNonAxis(i, j, ttCtx, tooltipEl) {
|
|
1140
|
-
const w = this.w
|
|
1141
|
-
|
|
1142
|
-
// For pie-like charts the series index IS the data point / slice index
|
|
1143
1130
|
ttCtx.tooltipLabels.drawSeriesTexts({
|
|
1144
1131
|
ttItems: ttCtx.ttItems,
|
|
1145
|
-
i: j,
|
|
1132
|
+
i: i + j,
|
|
1146
1133
|
shared: false,
|
|
1147
1134
|
})
|
|
1148
1135
|
|
|
@@ -1151,12 +1138,9 @@ export default class KeyboardNavigation {
|
|
|
1151
1138
|
const ttWidth = tooltipBound.width || ttCtx.tooltipRect.ttWidth || 0
|
|
1152
1139
|
const ttHeight = tooltipBound.height || ttCtx.tooltipRect.ttHeight || 0
|
|
1153
1140
|
|
|
1154
|
-
// Anchor on the arc
|
|
1155
|
-
// so keyboard and pointer land
|
|
1156
|
-
|
|
1157
|
-
// path directly, not on the parent group.
|
|
1158
|
-
const sliceEl = w.dom.baseEl.querySelector(`.apexcharts-pie-area[j='${j}']`)
|
|
1159
|
-
const anchor = ttCtx.getSliceAnchor(sliceEl)
|
|
1141
|
+
// Anchor on the arc's stamped centre (data:cx/cy), through the same helper
|
|
1142
|
+
// the mouse path uses so keyboard and pointer land in the same place.
|
|
1143
|
+
const anchor = ttCtx.getSliceAnchor(this._getFocusableElement(i, j))
|
|
1160
1144
|
if (anchor) {
|
|
1161
1145
|
const pos = ttCtx.tooltipPosition.placeOverAnchor(
|
|
1162
1146
|
anchor.x,
|
|
@@ -1169,68 +1153,6 @@ export default class KeyboardNavigation {
|
|
|
1169
1153
|
tooltipEl.style.top = pos.y + 'px'
|
|
1170
1154
|
}
|
|
1171
1155
|
}
|
|
1172
|
-
/**
|
|
1173
|
-
* radialBar — one ring per series, single value each
|
|
1174
|
-
* @param {number} i
|
|
1175
|
-
* @param {any} _j
|
|
1176
|
-
* @param {import('../tooltip/Tooltip').default} ttCtx
|
|
1177
|
-
* @param {HTMLElement} tooltipEl
|
|
1178
|
-
*/
|
|
1179
|
-
_showTooltipRadialBar(i, _j, ttCtx, tooltipEl) {
|
|
1180
|
-
const w = this.w
|
|
1181
|
-
|
|
1182
|
-
ttCtx.tooltipLabels.drawSeriesTexts({
|
|
1183
|
-
ttItems: ttCtx.ttItems,
|
|
1184
|
-
i,
|
|
1185
|
-
shared: false,
|
|
1186
|
-
})
|
|
1187
|
-
|
|
1188
|
-
const { ttWidth = 0, ttHeight = 0 } = ttCtx.getCachedDimensions()
|
|
1189
|
-
|
|
1190
|
-
// Each radial series is a ring; find the path and use its data:angle to
|
|
1191
|
-
// compute the centroid at the midpoint of the arc.
|
|
1192
|
-
const arcEl = w.dom.baseEl.querySelector(
|
|
1193
|
-
`.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`,
|
|
1194
|
-
)
|
|
1195
|
-
if (arcEl) {
|
|
1196
|
-
const angle = parseFloat(arcEl.getAttribute('data:angle') ?? '') || 0
|
|
1197
|
-
// Radial bars start from the top (initialAngle) and sweep clockwise
|
|
1198
|
-
const initialAngle = w.config.plotOptions.radialBar.startAngle || 0
|
|
1199
|
-
const midAngle = initialAngle + angle / 2
|
|
1200
|
-
|
|
1201
|
-
const centerX = w.layout.gridWidth / 2
|
|
1202
|
-
const centerY = w.layout.gridHeight / 2
|
|
1203
|
-
const radialSize =
|
|
1204
|
-
w.globals.radialSize ||
|
|
1205
|
-
Math.min(w.layout.gridWidth, w.layout.gridHeight) / 2
|
|
1206
|
-
|
|
1207
|
-
// Use the outer radius for this particular ring (series i)
|
|
1208
|
-
const seriesCount = w.seriesData.series.length
|
|
1209
|
-
const trackSize = radialSize / Math.max(seriesCount, 1)
|
|
1210
|
-
const outerRadius = radialSize - i * trackSize
|
|
1211
|
-
const innerRadius = outerRadius - trackSize
|
|
1212
|
-
const ringRadius = (outerRadius + innerRadius) / 2
|
|
1213
|
-
|
|
1214
|
-
const centroid = Utils.polarToCartesian(
|
|
1215
|
-
centerX,
|
|
1216
|
-
centerY,
|
|
1217
|
-
ringRadius,
|
|
1218
|
-
midAngle,
|
|
1219
|
-
)
|
|
1220
|
-
const x = centroid.x + (w.layout.translateX || 0)
|
|
1221
|
-
const y = centroid.y + (w.layout.translateY || 0)
|
|
1222
|
-
|
|
1223
|
-
const pos = ttCtx.tooltipPosition.placeOverAnchor(
|
|
1224
|
-
x,
|
|
1225
|
-
y,
|
|
1226
|
-
ttWidth,
|
|
1227
|
-
ttHeight,
|
|
1228
|
-
10,
|
|
1229
|
-
)
|
|
1230
|
-
tooltipEl.style.left = pos.x + 'px'
|
|
1231
|
-
tooltipEl.style.top = pos.y + 'px'
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
1156
|
/**
|
|
1235
1157
|
* heatmap / treemap — position tooltip using element bounding rect
|
|
1236
1158
|
* @param {number} i
|
|
@@ -1562,11 +1484,7 @@ export default class KeyboardNavigation {
|
|
|
1562
1484
|
const mark = this._canvasMark(i, j)
|
|
1563
1485
|
if (!mark) return this._drawCanvasMarkerFocusRing(i, j)
|
|
1564
1486
|
const w = this.w
|
|
1565
|
-
|
|
1566
|
-
// groups, which a combo has several of).
|
|
1567
|
-
const host = Array.from(
|
|
1568
|
-
w.dom.baseEl.querySelectorAll('.apexcharts-series'),
|
|
1569
|
-
).find((g) => g.getAttribute('data:realIndex') === String(i))
|
|
1487
|
+
const host = this._seriesGroup(i)
|
|
1570
1488
|
if (!host) return null
|
|
1571
1489
|
const ring = new Graphics(w, this.ctx).drawPath({
|
|
1572
1490
|
d: mark.d,
|
|
@@ -1591,9 +1509,7 @@ export default class KeyboardNavigation {
|
|
|
1591
1509
|
const marker = this._canvasMarker(i, j)
|
|
1592
1510
|
if (!marker) return null
|
|
1593
1511
|
const w = this.w
|
|
1594
|
-
const host =
|
|
1595
|
-
w.dom.baseEl.querySelectorAll('.apexcharts-series'),
|
|
1596
|
-
).find((g) => g.getAttribute('data:realIndex') === String(i))
|
|
1512
|
+
const host = this._seriesGroup(i)
|
|
1597
1513
|
if (!host) return null
|
|
1598
1514
|
const ring = new Graphics(w, this.ctx).drawPath({
|
|
1599
1515
|
d: marker.d,
|
|
@@ -1729,9 +1645,7 @@ export default class KeyboardNavigation {
|
|
|
1729
1645
|
}
|
|
1730
1646
|
|
|
1731
1647
|
if (type === 'radialBar') {
|
|
1732
|
-
return baseEl.querySelector(
|
|
1733
|
-
`.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`,
|
|
1734
|
-
)
|
|
1648
|
+
return baseEl.querySelector(`.apexcharts-radialbar-slice-${i}`)
|
|
1735
1649
|
}
|
|
1736
1650
|
|
|
1737
1651
|
if (this._isBarLikeSeries(i)) {
|
|
@@ -1739,31 +1653,44 @@ export default class KeyboardNavigation {
|
|
|
1739
1653
|
// it, _drawCanvasFocusRing), and a jitter path that still carries its
|
|
1740
1654
|
// `j` in the series is no stand-in for it.
|
|
1741
1655
|
if (this._canvasMark(i, j)) return null
|
|
1742
|
-
return
|
|
1743
|
-
`.apexcharts-series[data\\:realIndex='${i}'] path[j='${j}']`,
|
|
1744
|
-
)
|
|
1656
|
+
return this._seriesGroup(i)?.querySelector(`path[j='${j}']`)
|
|
1745
1657
|
}
|
|
1746
1658
|
|
|
1747
1659
|
// line / area / scatter / bubble / radar — try marker element
|
|
1748
|
-
|
|
1749
|
-
`.apexcharts-series[data\\:realIndex='${i}'] .apexcharts-marker[rel='${j}']`,
|
|
1750
|
-
)
|
|
1751
|
-
return marker || null
|
|
1660
|
+
return this._seriesGroup(i)?.querySelector(`.apexcharts-marker[rel='${j}']`)
|
|
1752
1661
|
}
|
|
1753
1662
|
|
|
1754
|
-
|
|
1663
|
+
/**
|
|
1664
|
+
* The series' own group, by realIndex (`rel` counts within a type's groups,
|
|
1665
|
+
* which a combo has several of). Matched in script: not every selector
|
|
1666
|
+
* engine takes the escaped `data\:realIndex` attribute.
|
|
1667
|
+
* @param {number} i
|
|
1668
|
+
* @returns {Element | undefined}
|
|
1669
|
+
*/
|
|
1670
|
+
_seriesGroup(i) {
|
|
1671
|
+
return Array.from(
|
|
1672
|
+
this.w.dom.baseEl.querySelectorAll('.apexcharts-series'),
|
|
1673
|
+
).find((g) => g.getAttribute('data:realIndex') === String(i))
|
|
1674
|
+
}
|
|
1755
1675
|
|
|
1756
|
-
|
|
1757
|
-
const w = this.w
|
|
1758
|
-
const ttCtx = w.globals.tooltip
|
|
1759
|
-
if (!ttCtx) return
|
|
1676
|
+
// ─── Click / Enter ────────────────────────────────────────────────────────
|
|
1760
1677
|
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1678
|
+
/**
|
|
1679
|
+
* What a click on the focused mark does: its mousedown selects it
|
|
1680
|
+
* (dataPointSelection), its mouseup slides a pie slice out and fires
|
|
1681
|
+
* markerClick.
|
|
1682
|
+
* @param {KeyboardEvent} e
|
|
1683
|
+
*/
|
|
1684
|
+
_fireClick(e) {
|
|
1685
|
+
const el = /** @type {any} */ (this._focusedEl)?.instance
|
|
1686
|
+
const pie = this.ctx.pie
|
|
1687
|
+
if (el) new Graphics(this.w, this.ctx).pathMouseDown(el, e)
|
|
1688
|
+
if (pie && pie.getExpandOffset() > 0) pie.pieClicked(this.dataPointIndex)
|
|
1689
|
+
this.w.globals.tooltip?.markerClick(
|
|
1690
|
+
e,
|
|
1691
|
+
this.seriesIndex,
|
|
1692
|
+
this.dataPointIndex,
|
|
1693
|
+
)
|
|
1767
1694
|
}
|
|
1768
1695
|
|
|
1769
1696
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
@@ -1795,8 +1722,9 @@ export default class KeyboardNavigation {
|
|
|
1795
1722
|
if (type === 'pie' || type === 'donut' || type === 'polarArea') {
|
|
1796
1723
|
return w.seriesData.series.length
|
|
1797
1724
|
}
|
|
1798
|
-
|
|
1799
|
-
|
|
1725
|
+
// A radialBar ring is a series of one value
|
|
1726
|
+
const s = w.seriesData.series[si]
|
|
1727
|
+
return Array.isArray(s) ? s.length : 1
|
|
1800
1728
|
}
|
|
1801
1729
|
|
|
1802
1730
|
_clampCursor() {
|
|
@@ -160,7 +160,7 @@ export function joinKeys(oldKeys, newKeys) {
|
|
|
160
160
|
* @param {string[]} keys
|
|
161
161
|
* @returns {string[]}
|
|
162
162
|
*/
|
|
163
|
-
function uniquifyKeys(keys) {
|
|
163
|
+
export function uniquifyKeys(keys) {
|
|
164
164
|
/** @type {Map<string, number>} */
|
|
165
165
|
const seen = new Map()
|
|
166
166
|
return keys.map((k) => {
|
|
@@ -170,6 +170,26 @@ function uniquifyKeys(keys) {
|
|
|
170
170
|
})
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Datum keys of a series, unique within it: repeated category labels (or a
|
|
175
|
+
* timeline's rows) would otherwise share one key, and the keyed bar morph
|
|
176
|
+
* would hand every duplicate the same previous bar.
|
|
177
|
+
*
|
|
178
|
+
* @param {import('../../types/internal').ChartStateW} w
|
|
179
|
+
* @param {number} realIndex
|
|
180
|
+
* @param {number} [n] how many datums (default: the parsed series length)
|
|
181
|
+
* @returns {string[]}
|
|
182
|
+
*/
|
|
183
|
+
export function seriesKeys(
|
|
184
|
+
w,
|
|
185
|
+
realIndex,
|
|
186
|
+
n = w.seriesData.series[realIndex]?.length | 0,
|
|
187
|
+
) {
|
|
188
|
+
return uniquifyKeys(
|
|
189
|
+
Array.from({ length: n }, (_, j) => datumKey(w, realIndex, j)),
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
/**
|
|
174
194
|
* The keyed join for one series against the captured previous frame, or null
|
|
175
195
|
* when this render is not an animated update for that series (no frame,
|
|
@@ -212,7 +232,7 @@ export function seriesJoin(
|
|
|
212
232
|
const oldKeys = uniquifyKeys(
|
|
213
233
|
oldY.map((_, j) => frameDatumKey(frame, realIndex, j)),
|
|
214
234
|
)
|
|
215
|
-
const newKeys =
|
|
235
|
+
const newKeys = seriesKeys(w, realIndex)
|
|
216
236
|
const join = joinKeys(oldKeys, newKeys)
|
|
217
237
|
if (!join.ordered && !allowReorder) return null
|
|
218
238
|
if (!join.changed && !includeIdentity) return null
|
|
@@ -39,8 +39,11 @@ export default class Breadcrumb {
|
|
|
39
39
|
const elWrap = w.dom.elWrap
|
|
40
40
|
if (!elWrap) return
|
|
41
41
|
|
|
42
|
-
// Remove any stale breadcrumb first (guards against double-render)
|
|
43
|
-
|
|
42
|
+
// Remove any stale breadcrumb first (guards against double-render), but
|
|
43
|
+
// only its own: a zoomed treemap's shares the class.
|
|
44
|
+
const existing = elWrap.querySelector(
|
|
45
|
+
'.apexcharts-breadcrumb[aria-label^=Drill]',
|
|
46
|
+
)
|
|
44
47
|
if (existing && existing.parentNode) {
|
|
45
48
|
existing.parentNode.removeChild(existing)
|
|
46
49
|
}
|
|
@@ -64,7 +64,7 @@ export default class Destroy {
|
|
|
64
64
|
// alone leaks the listener + the dead instance on every updateOptions().
|
|
65
65
|
// zoomPanSelection/toolbar were destroyed above; the full-destroy path
|
|
66
66
|
// destroys keyboardNavigation via apexcharts.js before calling clear().
|
|
67
|
-
this.ctx._keyboardNavigation?.destroy()
|
|
67
|
+
this.ctx._keyboardNavigation?.destroy(true)
|
|
68
68
|
this.ctx._keyboardNavigation = null
|
|
69
69
|
} else {
|
|
70
70
|
// Full destroy — null everything so GC can collect the instances.
|
|
@@ -31,7 +31,6 @@ import Utils from '../../utils/Utils'
|
|
|
31
31
|
import { prefersReducedMotion } from '../Animations'
|
|
32
32
|
import DataLabels from '../DataLabels'
|
|
33
33
|
import {
|
|
34
|
-
datumKey,
|
|
35
34
|
morphEasing,
|
|
36
35
|
reconcileSeriesPaths,
|
|
37
36
|
seriesJoin,
|
|
@@ -739,8 +738,10 @@ export default class HighlightFilter {
|
|
|
739
738
|
// A chart that is not highlighting and was not a frame ago: one check.
|
|
740
739
|
if (!active && !prevMap?.size) return undefined
|
|
741
740
|
const { j, realIndex } = o
|
|
742
|
-
//
|
|
743
|
-
|
|
741
|
+
// The bar's own key: the category, which every series shares at that x,
|
|
742
|
+
// made unique per occurrence so a repeated category keeps its own part
|
|
743
|
+
// (and matches the exit ghost's name).
|
|
744
|
+
const key = BAR + `${realIndex}::${bar._keys(realIndex)[j]}`
|
|
744
745
|
this._seen.add(key)
|
|
745
746
|
const prev = prevMap?.get(key)
|
|
746
747
|
const p = active ? hd.parts[realIndex]?.[j] : null
|
|
@@ -1114,8 +1115,8 @@ export default class HighlightFilter {
|
|
|
1114
1115
|
|
|
1115
1116
|
/**
|
|
1116
1117
|
* The stack a stacked bar datum joins, as the renderer resolves it
|
|
1117
|
-
* (BarStacked
|
|
1118
|
-
*
|
|
1118
|
+
* (BarStacked): its series group, then its x value on a numeric or
|
|
1119
|
+
* datetime axis, else its index.
|
|
1119
1120
|
* @param {number} i @param {number} j
|
|
1120
1121
|
*/
|
|
1121
1122
|
_barKey(i, j) {
|
|
@@ -1123,9 +1124,7 @@ export default class HighlightFilter {
|
|
|
1123
1124
|
return (
|
|
1124
1125
|
w.labelData.seriesGroupIndex[i] +
|
|
1125
1126
|
'|' +
|
|
1126
|
-
(
|
|
1127
|
-
? w.seriesData.seriesX[i]?.[j]
|
|
1128
|
-
: j)
|
|
1127
|
+
(w.axisFlags.isXNumeric ? w.seriesData.seriesX[i]?.[j] : j)
|
|
1129
1128
|
)
|
|
1130
1129
|
}
|
|
1131
1130
|
|
|
@@ -1233,7 +1232,7 @@ export default class HighlightFilter {
|
|
|
1233
1232
|
? this._lineBase(ln, type, series, i, realIndex, ti, has ? raw : null)
|
|
1234
1233
|
: null
|
|
1235
1234
|
if (pp && w.config.chart.stacked) {
|
|
1236
|
-
this._swap(ln, () => ln._recordStackTops(realIndex, pp.yArrj))
|
|
1235
|
+
this._swap(ln, () => ln._recordStackTops(realIndex, pp.yArrj, pp.S[i]))
|
|
1237
1236
|
this._stkPrev.push(pp.yArrj)
|
|
1238
1237
|
}
|
|
1239
1238
|
if (exit) {
|
|
@@ -414,10 +414,10 @@ function wrapParentTip(hf, tm) {
|
|
|
414
414
|
}
|
|
415
415
|
const v = tm._tip()?.querySelector('.apexcharts-tooltip-text-y-value')
|
|
416
416
|
if (!v) return
|
|
417
|
-
let rest = `/ ${tm._formatValue(h.total)}`
|
|
417
|
+
let rest = `/ ${tm._formatValue(h.total, node._si)}`
|
|
418
418
|
if (tt.share && h.total) rest += ` · ${Math.round(h.share * 100)}%`
|
|
419
419
|
v.innerHTML =
|
|
420
|
-
`${tm._formatValue(h.value)} ` +
|
|
420
|
+
`${tm._formatValue(h.value, node._si)} ` +
|
|
421
421
|
`<span class="apexcharts-highlight-total" style="font-weight: 400; opacity: 0.6">${rest}</span>`
|
|
422
422
|
}
|
|
423
423
|
}
|