@mui/x-charts 9.12.0 → 9.14.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/BarChart/BarChart.js +1 -1
- package/BarChart/BarChart.mjs +1 -1
- package/CHANGELOG.md +301 -0
- package/ChartsContainer/ChartsContainer.js +1 -1
- package/ChartsContainer/ChartsContainer.mjs +1 -1
- package/ChartsXAxis/useAxisTicksProps.js +2 -1
- package/ChartsXAxis/useAxisTicksProps.mjs +2 -1
- package/ChartsYAxis/shortenLabels.js +16 -26
- package/ChartsYAxis/shortenLabels.mjs +17 -27
- package/ChartsYAxis/useAxisTicksProps.js +2 -1
- package/ChartsYAxis/useAxisTicksProps.mjs +2 -1
- package/LineChart/LineChart.js +1 -1
- package/LineChart/LineChart.mjs +1 -1
- package/LineChart/MarkElement.js +13 -6
- package/LineChart/MarkElement.mjs +13 -6
- package/RadarChart/RadarChart.js +1 -1
- package/RadarChart/RadarChart.mjs +1 -1
- package/RadarChart/RadarSeriesPlot/RadarSeriesMarks.js +6 -2
- package/RadarChart/RadarSeriesPlot/RadarSeriesMarks.mjs +6 -2
- package/RadarChart/RadarSeriesPlot/RadarSeriesPlot.js +2 -1
- package/RadarChart/RadarSeriesPlot/RadarSeriesPlot.mjs +2 -1
- package/ScatterChart/ScatterChart.js +1 -1
- package/ScatterChart/ScatterChart.mjs +1 -1
- package/SparkLineChart/SparkLineChart.js +1 -1
- package/SparkLineChart/SparkLineChart.mjs +1 -1
- package/constants/index.d.mts +3 -1
- package/constants/index.d.ts +3 -1
- package/constants/index.js +5 -2
- package/constants/index.mjs +4 -1
- package/hooks/animation/index.d.mts +1 -0
- package/hooks/animation/index.d.ts +1 -0
- package/hooks/animation/index.js +11 -0
- package/hooks/animation/index.mjs +1 -0
- package/hooks/animation/useAnimateMark.d.mts +25 -0
- package/hooks/animation/useAnimateMark.d.ts +25 -0
- package/hooks/animation/useAnimateMark.js +45 -0
- package/hooks/animation/useAnimateMark.mjs +39 -0
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internals/components/ChartsAccessibilityProxy/ChartsAccessibilityProxy.js +31 -8
- package/internals/components/ChartsAccessibilityProxy/ChartsAccessibilityProxy.mjs +32 -9
- package/internals/components/ChartsAccessibilityProxy/useZoomAnnouncement.d.mts +9 -0
- package/internals/components/ChartsAccessibilityProxy/useZoomAnnouncement.d.ts +9 -0
- package/internals/components/ChartsAccessibilityProxy/useZoomAnnouncement.js +67 -0
- package/internals/components/ChartsAccessibilityProxy/useZoomAnnouncement.mjs +62 -0
- package/internals/domUtils.js +17 -16
- package/internals/domUtils.mjs +17 -15
- package/internals/ellipsize.d.mts +30 -0
- package/internals/ellipsize.d.ts +30 -0
- package/internals/ellipsize.js +60 -0
- package/internals/ellipsize.mjs +59 -0
- package/internals/index.d.mts +1 -0
- package/internals/index.d.ts +1 -0
- package/internals/index.js +8 -0
- package/internals/index.mjs +1 -0
- package/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisAutoSize.d.mts +3 -0
- package/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisAutoSize.d.ts +3 -0
- package/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisAutoSize.js +9 -5
- package/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisAutoSize.mjs +9 -5
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartAxisAutoSize.selectors.js +9 -4
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartAxisAutoSize.selectors.mjs +9 -4
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.js +75 -3
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.mjs +76 -3
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.mts +6 -2
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts +6 -2
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisLayout.selectors.d.mts +1 -0
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisLayout.selectors.d.ts +1 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js +59 -16
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.mjs +59 -16
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.d.mts +3 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.d.ts +3 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.js +2 -1
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.mjs +1 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.types.d.mts +12 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.types.d.ts +12 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/utils/getItemAtRotationIndex.d.mts +18 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/utils/getItemAtRotationIndex.d.ts +18 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/utils/getItemAtRotationIndex.js +65 -0
- package/internals/plugins/featurePlugins/useChartKeyboardNavigation/utils/getItemAtRotationIndex.mjs +60 -0
- package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.js +43 -1
- package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.mjs +43 -1
- package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.types.d.mts +3 -2
- package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.types.d.ts +3 -2
- package/internals/useDefaultTickLabelStyle.d.mts +7 -0
- package/internals/useDefaultTickLabelStyle.d.ts +7 -0
- package/internals/useDefaultTickLabelStyle.js +34 -0
- package/internals/useDefaultTickLabelStyle.mjs +28 -0
- package/locales/elGR.d.mts +5 -0
- package/locales/elGR.d.ts +5 -0
- package/locales/elGR.js +8 -0
- package/locales/elGR.mjs +8 -0
- package/locales/enUS.d.mts +5 -0
- package/locales/enUS.d.ts +5 -0
- package/locales/enUS.js +8 -0
- package/locales/enUS.mjs +8 -0
- package/locales/frFR.d.mts +5 -0
- package/locales/frFR.d.ts +5 -0
- package/locales/frFR.js +8 -0
- package/locales/frFR.mjs +8 -0
- package/locales/nbNO.d.mts +5 -0
- package/locales/nbNO.d.ts +5 -0
- package/locales/nbNO.js +8 -0
- package/locales/nbNO.mjs +8 -0
- package/locales/ptBR.d.mts +5 -0
- package/locales/ptBR.d.ts +5 -0
- package/locales/ptBR.js +8 -0
- package/locales/ptBR.mjs +8 -0
- package/locales/ptPT.d.mts +5 -0
- package/locales/ptPT.d.ts +5 -0
- package/locales/ptPT.js +8 -0
- package/locales/ptPT.mjs +8 -0
- package/locales/svSE.d.mts +5 -0
- package/locales/svSE.d.ts +5 -0
- package/locales/svSE.js +8 -0
- package/locales/svSE.mjs +8 -0
- package/locales/utils/chartsLocaleTextApi.d.mts +14 -0
- package/locales/utils/chartsLocaleTextApi.d.ts +14 -0
- package/locales/utils/getChartsLocalization.d.mts +5 -0
- package/locales/utils/getChartsLocalization.d.ts +5 -0
- package/package.json +7 -7
package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartAxisAutoSize.selectors.mjs
CHANGED
|
@@ -5,6 +5,9 @@ import { selectorChartXAxisDomainsForAutoSize, selectorChartYAxisDomainsForAutoS
|
|
|
5
5
|
|
|
6
6
|
// Direct state access to avoid circular dependency
|
|
7
7
|
const selectorIsHydrated = state => state.dimensions.width && state.dimensions.height;
|
|
8
|
+
|
|
9
|
+
// Direct state access to avoid circular dependency
|
|
10
|
+
const selectorDefaultTickLabelStyle = state => state.cartesianAxis?.defaultTickLabelStyle;
|
|
8
11
|
const EMPTY_SIZES = {};
|
|
9
12
|
const EMPTY_RESULTS = {};
|
|
10
13
|
|
|
@@ -12,7 +15,7 @@ const EMPTY_RESULTS = {};
|
|
|
12
15
|
* Selector that computes full auto-size results for X axes that have `height: 'auto'`.
|
|
13
16
|
* Returns a map of axis ID to full result (including group tick sizes for grouped axes).
|
|
14
17
|
*/
|
|
15
|
-
export const selectorChartXAxisAutoSizeResults = createSelectorMemoized(selectorChartRawXAxis, selectorIsHydrated, selectorChartXAxisDomainsForAutoSize, function selectorChartXAxisAutoSizeResults(xAxes, isHydrated, domainsMap) {
|
|
18
|
+
export const selectorChartXAxisAutoSizeResults = createSelectorMemoized(selectorChartRawXAxis, selectorIsHydrated, selectorChartXAxisDomainsForAutoSize, selectorDefaultTickLabelStyle, function selectorChartXAxisAutoSizeResults(xAxes, isHydrated, domainsMap, defaultTickLabelStyle) {
|
|
16
19
|
const hasAutoAxis = xAxes?.some(axis => axis.height === 'auto');
|
|
17
20
|
if (!hasAutoAxis || !isHydrated) {
|
|
18
21
|
return EMPTY_RESULTS;
|
|
@@ -24,7 +27,8 @@ export const selectorChartXAxisAutoSizeResults = createSelectorMemoized(selector
|
|
|
24
27
|
const computed = computeAxisAutoSize({
|
|
25
28
|
axis,
|
|
26
29
|
direction: 'x',
|
|
27
|
-
domain: domainsMap[axis.id]
|
|
30
|
+
domain: domainsMap[axis.id],
|
|
31
|
+
defaultTickLabelStyle
|
|
28
32
|
});
|
|
29
33
|
if (computed !== undefined) {
|
|
30
34
|
results[axis.id] = computed;
|
|
@@ -53,7 +57,7 @@ export const selectorChartXAxisAutoSizes = createSelectorMemoized(selectorChartX
|
|
|
53
57
|
* Selector that computes full auto-size results for Y axes that have `width: 'auto'`.
|
|
54
58
|
* Returns a map of axis ID to full result (including group tick sizes for grouped axes).
|
|
55
59
|
*/
|
|
56
|
-
export const selectorChartYAxisAutoSizeResults = createSelectorMemoized(selectorChartRawYAxis, selectorIsHydrated, selectorChartYAxisDomainsForAutoSize, function selectorChartYAxisAutoSizeResults(yAxes, isHydrated, domainsMap) {
|
|
60
|
+
export const selectorChartYAxisAutoSizeResults = createSelectorMemoized(selectorChartRawYAxis, selectorIsHydrated, selectorChartYAxisDomainsForAutoSize, selectorDefaultTickLabelStyle, function selectorChartYAxisAutoSizeResults(yAxes, isHydrated, domainsMap, defaultTickLabelStyle) {
|
|
57
61
|
const hasAutoAxis = yAxes?.some(axis => axis.width === 'auto');
|
|
58
62
|
if (!hasAutoAxis || !isHydrated) {
|
|
59
63
|
return EMPTY_RESULTS;
|
|
@@ -65,7 +69,8 @@ export const selectorChartYAxisAutoSizeResults = createSelectorMemoized(selector
|
|
|
65
69
|
const computed = computeAxisAutoSize({
|
|
66
70
|
axis,
|
|
67
71
|
direction: 'y',
|
|
68
|
-
domain: domainsMap[axis.id]
|
|
72
|
+
domain: domainsMap[axis.id],
|
|
73
|
+
defaultTickLabelStyle
|
|
69
74
|
});
|
|
70
75
|
if (computed !== undefined) {
|
|
71
76
|
results[axis.id] = computed;
|
|
@@ -10,6 +10,7 @@ exports.useChartCartesianAxis = void 0;
|
|
|
10
10
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
11
11
|
var React = _interopRequireWildcard(require("react"));
|
|
12
12
|
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
|
|
13
|
+
var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
|
|
13
14
|
var _store = require("@mui/x-internals/store");
|
|
14
15
|
var _useAssertModelConsistency = require("@mui/x-internals/useAssertModelConsistency");
|
|
15
16
|
var _warning = require("@mui/x-internals/warning");
|
|
@@ -23,6 +24,15 @@ var _useChartInteraction = require("../useChartInteraction");
|
|
|
23
24
|
var _useChartCartesianInteraction = require("./useChartCartesianInteraction.selectors");
|
|
24
25
|
var _checkHasInteractionPlugin = require("../useChartInteraction/checkHasInteractionPlugin");
|
|
25
26
|
var _getAxisClickPayload = require("./getAxisClickPayload");
|
|
27
|
+
var _useDefaultTickLabelStyle = require("../../../useDefaultTickLabelStyle");
|
|
28
|
+
var _useChartKeyboardNavigation = require("../useChartKeyboardNavigation");
|
|
29
|
+
/**
|
|
30
|
+
* Narrows an axis item to one the axis actually has a value for.
|
|
31
|
+
* Axes unrelated to the focused series can exist with empty data, so the index must resolve.
|
|
32
|
+
*/
|
|
33
|
+
function hasAxisValueAt(axes, item) {
|
|
34
|
+
return item !== undefined && item.dataIndex !== undefined && axes[item.axisId]?.data?.[item.dataIndex] !== undefined;
|
|
35
|
+
}
|
|
26
36
|
const useChartCartesianAxis = ({
|
|
27
37
|
params,
|
|
28
38
|
store,
|
|
@@ -39,6 +49,12 @@ const useChartCartesianAxis = ({
|
|
|
39
49
|
onTooltipAxisChange,
|
|
40
50
|
axesGap
|
|
41
51
|
} = params;
|
|
52
|
+
const defaultTickLabelStyle = (0, _useDefaultTickLabelStyle.useDefaultTickLabelStyle)();
|
|
53
|
+
(0, _useEnhancedEffect.default)(() => {
|
|
54
|
+
store.set('cartesianAxis', (0, _extends2.default)({}, store.state.cartesianAxis, {
|
|
55
|
+
defaultTickLabelStyle
|
|
56
|
+
}));
|
|
57
|
+
}, [defaultTickLabelStyle, store]);
|
|
42
58
|
if (process.env.NODE_ENV !== 'production') {
|
|
43
59
|
const ids = [...(xAxis ?? []), ...(yAxis ?? [])].filter(axis => axis.id).map(axis => axis.id);
|
|
44
60
|
const duplicates = new Set(ids.filter((id, index) => ids.indexOf(id) !== index));
|
|
@@ -92,9 +108,10 @@ const useChartCartesianAxis = ({
|
|
|
92
108
|
store.set('cartesianAxis', {
|
|
93
109
|
axesGap,
|
|
94
110
|
x: (0, _defaultizeAxis.defaultizeXAxis)(xAxis, dataset, axesGap),
|
|
95
|
-
y: (0, _defaultizeAxis.defaultizeYAxis)(yAxis, dataset, axesGap)
|
|
111
|
+
y: (0, _defaultizeAxis.defaultizeYAxis)(yAxis, dataset, axesGap),
|
|
112
|
+
defaultTickLabelStyle
|
|
96
113
|
});
|
|
97
|
-
}, [xAxis, yAxis, dataset, axesGap, store]);
|
|
114
|
+
}, [xAxis, yAxis, dataset, axesGap, defaultTickLabelStyle, store]);
|
|
98
115
|
const usedXAxis = xAxisIds[0];
|
|
99
116
|
const usedYAxis = yAxisIds[0];
|
|
100
117
|
(0, _store.useStoreEffect)(store, _useChartCartesianInteraction.selectorChartAxisInteraction, (prevAxisInteraction, nextAxisInteraction) => {
|
|
@@ -197,7 +214,62 @@ const useChartCartesianAxis = ({
|
|
|
197
214
|
return () => {
|
|
198
215
|
axisClickHandler.cleanup();
|
|
199
216
|
};
|
|
200
|
-
}, [params.onAxisClick, processedSeries, chartsLayerContainerRef, xAxisWithScale, xAxisIds, yAxisWithScale, yAxisIds, usedXAxis, usedYAxis, instance]);
|
|
217
|
+
}, [params.onAxisClick, processedSeries, store, chartsLayerContainerRef, xAxisWithScale, xAxisIds, yAxisWithScale, yAxisIds, usedXAxis, usedYAxis, instance]);
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Kept separate from the pointer effect: this listener must survive re-renders, so it reads the
|
|
221
|
+
* axes and the callback when the key is pressed rather than closing over them. Re-subscribing per
|
|
222
|
+
* render would drop keystrokes landing between a keyboard navigation update and its commit.
|
|
223
|
+
*/
|
|
224
|
+
const handleKeyboardActivation = (0, _useEventCallback.default)(event => {
|
|
225
|
+
const onAxisClick = params.onAxisClick;
|
|
226
|
+
if (!onAxisClick ||
|
|
227
|
+
// Ignore the auto-repeat while the key is held: a pointer click does not repeat either.
|
|
228
|
+
event.repeat || !(0, _useChartKeyboardNavigation.isItemActivationKey)(event) || !(0, _useChartKeyboardNavigation.selectorChartsIsKeyboardActivationEnabled)(store.state)) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const {
|
|
232
|
+
axis: xAxes
|
|
233
|
+
} = (0, _useChartCartesianAxisRendering.selectorChartXAxis)(store.state);
|
|
234
|
+
const {
|
|
235
|
+
axis: yAxes
|
|
236
|
+
} = (0, _useChartCartesianAxisRendering.selectorChartYAxis)(store.state);
|
|
237
|
+
const xAxisItem = (0, _useChartKeyboardNavigation.selectorChartsKeyboardXAxisIndex)(store.state);
|
|
238
|
+
const yAxisItem = (0, _useChartKeyboardNavigation.selectorChartsKeyboardYAxisIndex)(store.state);
|
|
239
|
+
const focusedAxisItem = hasAxisValueAt(xAxes, xAxisItem) ? {
|
|
240
|
+
item: xAxisItem,
|
|
241
|
+
isXAxis: true
|
|
242
|
+
} : hasAxisValueAt(yAxes, yAxisItem) && {
|
|
243
|
+
item: yAxisItem,
|
|
244
|
+
isXAxis: false
|
|
245
|
+
};
|
|
246
|
+
if (!focusedAxisItem) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const payload = (0, _getAxisClickPayload.getAxisClickPayload)({
|
|
250
|
+
axisId: focusedAxisItem.item.axisId,
|
|
251
|
+
dataIndex: focusedAxisItem.item.dataIndex,
|
|
252
|
+
isXAxis: focusedAxisItem.isXAxis,
|
|
253
|
+
axes: focusedAxisItem.isXAxis ? xAxes : yAxes,
|
|
254
|
+
processedSeries: (0, _useChartSeries.selectorChartSeriesProcessed)(store.state)
|
|
255
|
+
});
|
|
256
|
+
if (payload === null) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
event.preventDefault();
|
|
260
|
+
// The callback only describes the pointer event unless the user augments the types.
|
|
261
|
+
onAxisClick(event, payload);
|
|
262
|
+
});
|
|
263
|
+
React.useEffect(() => {
|
|
264
|
+
const element = chartsLayerContainerRef.current;
|
|
265
|
+
if (element === null) {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
element.addEventListener('keydown', handleKeyboardActivation);
|
|
269
|
+
return () => {
|
|
270
|
+
element.removeEventListener('keydown', handleKeyboardActivation);
|
|
271
|
+
};
|
|
272
|
+
}, [chartsLayerContainerRef, handleKeyboardActivation]);
|
|
201
273
|
return {};
|
|
202
274
|
};
|
|
203
275
|
exports.useChartCartesianAxis = useChartCartesianAxis;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
6
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
6
7
|
import { useStoreEffect } from '@mui/x-internals/store';
|
|
7
8
|
import { useAssertModelConsistency } from '@mui/x-internals/useAssertModelConsistency';
|
|
8
9
|
import { warnOnce } from '@mui/x-internals/warning';
|
|
@@ -16,6 +17,16 @@ import { selectorChartsInteractionIsInitialized } from "../useChartInteraction/i
|
|
|
16
17
|
import { selectorChartAxisInteraction } from "./useChartCartesianInteraction.selectors.mjs";
|
|
17
18
|
import { checkHasInteractionPlugin } from "../useChartInteraction/checkHasInteractionPlugin.mjs";
|
|
18
19
|
import { getAxisClickPayload } from "./getAxisClickPayload.mjs";
|
|
20
|
+
import { useDefaultTickLabelStyle } from "../../../useDefaultTickLabelStyle.mjs";
|
|
21
|
+
import { isItemActivationKey, selectorChartsIsKeyboardActivationEnabled, selectorChartsKeyboardXAxisIndex, selectorChartsKeyboardYAxisIndex } from "../useChartKeyboardNavigation/index.mjs";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Narrows an axis item to one the axis actually has a value for.
|
|
25
|
+
* Axes unrelated to the focused series can exist with empty data, so the index must resolve.
|
|
26
|
+
*/
|
|
27
|
+
function hasAxisValueAt(axes, item) {
|
|
28
|
+
return item !== undefined && item.dataIndex !== undefined && axes[item.axisId]?.data?.[item.dataIndex] !== undefined;
|
|
29
|
+
}
|
|
19
30
|
export const useChartCartesianAxis = ({
|
|
20
31
|
params,
|
|
21
32
|
store,
|
|
@@ -32,6 +43,12 @@ export const useChartCartesianAxis = ({
|
|
|
32
43
|
onTooltipAxisChange,
|
|
33
44
|
axesGap
|
|
34
45
|
} = params;
|
|
46
|
+
const defaultTickLabelStyle = useDefaultTickLabelStyle();
|
|
47
|
+
useEnhancedEffect(() => {
|
|
48
|
+
store.set('cartesianAxis', _extends({}, store.state.cartesianAxis, {
|
|
49
|
+
defaultTickLabelStyle
|
|
50
|
+
}));
|
|
51
|
+
}, [defaultTickLabelStyle, store]);
|
|
35
52
|
if (process.env.NODE_ENV !== 'production') {
|
|
36
53
|
const ids = [...(xAxis ?? []), ...(yAxis ?? [])].filter(axis => axis.id).map(axis => axis.id);
|
|
37
54
|
const duplicates = new Set(ids.filter((id, index) => ids.indexOf(id) !== index));
|
|
@@ -85,9 +102,10 @@ export const useChartCartesianAxis = ({
|
|
|
85
102
|
store.set('cartesianAxis', {
|
|
86
103
|
axesGap,
|
|
87
104
|
x: defaultizeXAxis(xAxis, dataset, axesGap),
|
|
88
|
-
y: defaultizeYAxis(yAxis, dataset, axesGap)
|
|
105
|
+
y: defaultizeYAxis(yAxis, dataset, axesGap),
|
|
106
|
+
defaultTickLabelStyle
|
|
89
107
|
});
|
|
90
|
-
}, [xAxis, yAxis, dataset, axesGap, store]);
|
|
108
|
+
}, [xAxis, yAxis, dataset, axesGap, defaultTickLabelStyle, store]);
|
|
91
109
|
const usedXAxis = xAxisIds[0];
|
|
92
110
|
const usedYAxis = yAxisIds[0];
|
|
93
111
|
useStoreEffect(store, selectorChartAxisInteraction, (prevAxisInteraction, nextAxisInteraction) => {
|
|
@@ -190,7 +208,62 @@ export const useChartCartesianAxis = ({
|
|
|
190
208
|
return () => {
|
|
191
209
|
axisClickHandler.cleanup();
|
|
192
210
|
};
|
|
193
|
-
}, [params.onAxisClick, processedSeries, chartsLayerContainerRef, xAxisWithScale, xAxisIds, yAxisWithScale, yAxisIds, usedXAxis, usedYAxis, instance]);
|
|
211
|
+
}, [params.onAxisClick, processedSeries, store, chartsLayerContainerRef, xAxisWithScale, xAxisIds, yAxisWithScale, yAxisIds, usedXAxis, usedYAxis, instance]);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Kept separate from the pointer effect: this listener must survive re-renders, so it reads the
|
|
215
|
+
* axes and the callback when the key is pressed rather than closing over them. Re-subscribing per
|
|
216
|
+
* render would drop keystrokes landing between a keyboard navigation update and its commit.
|
|
217
|
+
*/
|
|
218
|
+
const handleKeyboardActivation = useEventCallback(event => {
|
|
219
|
+
const onAxisClick = params.onAxisClick;
|
|
220
|
+
if (!onAxisClick ||
|
|
221
|
+
// Ignore the auto-repeat while the key is held: a pointer click does not repeat either.
|
|
222
|
+
event.repeat || !isItemActivationKey(event) || !selectorChartsIsKeyboardActivationEnabled(store.state)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const {
|
|
226
|
+
axis: xAxes
|
|
227
|
+
} = selectorChartXAxis(store.state);
|
|
228
|
+
const {
|
|
229
|
+
axis: yAxes
|
|
230
|
+
} = selectorChartYAxis(store.state);
|
|
231
|
+
const xAxisItem = selectorChartsKeyboardXAxisIndex(store.state);
|
|
232
|
+
const yAxisItem = selectorChartsKeyboardYAxisIndex(store.state);
|
|
233
|
+
const focusedAxisItem = hasAxisValueAt(xAxes, xAxisItem) ? {
|
|
234
|
+
item: xAxisItem,
|
|
235
|
+
isXAxis: true
|
|
236
|
+
} : hasAxisValueAt(yAxes, yAxisItem) && {
|
|
237
|
+
item: yAxisItem,
|
|
238
|
+
isXAxis: false
|
|
239
|
+
};
|
|
240
|
+
if (!focusedAxisItem) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const payload = getAxisClickPayload({
|
|
244
|
+
axisId: focusedAxisItem.item.axisId,
|
|
245
|
+
dataIndex: focusedAxisItem.item.dataIndex,
|
|
246
|
+
isXAxis: focusedAxisItem.isXAxis,
|
|
247
|
+
axes: focusedAxisItem.isXAxis ? xAxes : yAxes,
|
|
248
|
+
processedSeries: selectorChartSeriesProcessed(store.state)
|
|
249
|
+
});
|
|
250
|
+
if (payload === null) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
// The callback only describes the pointer event unless the user augments the types.
|
|
255
|
+
onAxisClick(event, payload);
|
|
256
|
+
});
|
|
257
|
+
React.useEffect(() => {
|
|
258
|
+
const element = chartsLayerContainerRef.current;
|
|
259
|
+
if (element === null) {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
element.addEventListener('keydown', handleKeyboardActivation);
|
|
263
|
+
return () => {
|
|
264
|
+
element.removeEventListener('keydown', handleKeyboardActivation);
|
|
265
|
+
};
|
|
266
|
+
}, [chartsLayerContainerRef, handleKeyboardActivation]);
|
|
194
267
|
return {};
|
|
195
268
|
};
|
|
196
269
|
useChartCartesianAxis.params = {
|
package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.mts
CHANGED
|
@@ -7,6 +7,8 @@ import type { UseChartInteractionSignature } from "../useChartInteraction/index.
|
|
|
7
7
|
import type { ChartsAxisProps } from "../../../../ChartsAxis/index.mjs";
|
|
8
8
|
import type { UseChartBrushSignature } from "../useChartBrush/index.mjs";
|
|
9
9
|
import type { SamplingState } from "./sampling.types.mjs";
|
|
10
|
+
import type { ChartsActivationEvent } from "../../../../models/events.mjs";
|
|
11
|
+
import type { ChartsTextStyle } from "../../../getWordsByLines.mjs";
|
|
10
12
|
/**
|
|
11
13
|
* The axes' configuration after computing.
|
|
12
14
|
* An axis in this state already contains a scale function and all the necessary properties to be rendered.
|
|
@@ -34,10 +36,10 @@ export interface UseChartCartesianAxisParameters<S extends ScaleName = ScaleName
|
|
|
34
36
|
/**
|
|
35
37
|
* The function called for onClick events.
|
|
36
38
|
* The second argument contains information about all line/bar elements at the current mouse position.
|
|
37
|
-
* @param {
|
|
39
|
+
* @param {ChartsActivationEvent} event The event recorded on the `<svg/>` element.
|
|
38
40
|
* @param {null | ChartsAxisData} data The data about the clicked axis and items associated with it.
|
|
39
41
|
*/
|
|
40
|
-
onAxisClick?: (event:
|
|
42
|
+
onAxisClick?: (event: ChartsActivationEvent, data: null | ChartsAxisData) => void;
|
|
41
43
|
/**
|
|
42
44
|
* The function called when the pointer position corresponds to a new axis data item.
|
|
43
45
|
* This update can either be caused by a pointer movement, or an axis update.
|
|
@@ -106,6 +108,8 @@ export interface UseChartCartesianAxisState {
|
|
|
106
108
|
axesGap: number;
|
|
107
109
|
x: DefaultedXAxis[];
|
|
108
110
|
y: DefaultedYAxis[];
|
|
111
|
+
/** Only used to measure tick labels. Never merged into the rendered tick style. */
|
|
112
|
+
defaultTickLabelStyle?: ChartsTextStyle;
|
|
109
113
|
};
|
|
110
114
|
/**
|
|
111
115
|
* The controlled axis item highlighted.
|
package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ import type { UseChartInteractionSignature } from "../useChartInteraction/index.
|
|
|
7
7
|
import type { ChartsAxisProps } from "../../../../ChartsAxis/index.js";
|
|
8
8
|
import type { UseChartBrushSignature } from "../useChartBrush/index.js";
|
|
9
9
|
import type { SamplingState } from "./sampling.types.js";
|
|
10
|
+
import type { ChartsActivationEvent } from "../../../../models/events.js";
|
|
11
|
+
import type { ChartsTextStyle } from "../../../getWordsByLines.js";
|
|
10
12
|
/**
|
|
11
13
|
* The axes' configuration after computing.
|
|
12
14
|
* An axis in this state already contains a scale function and all the necessary properties to be rendered.
|
|
@@ -34,10 +36,10 @@ export interface UseChartCartesianAxisParameters<S extends ScaleName = ScaleName
|
|
|
34
36
|
/**
|
|
35
37
|
* The function called for onClick events.
|
|
36
38
|
* The second argument contains information about all line/bar elements at the current mouse position.
|
|
37
|
-
* @param {
|
|
39
|
+
* @param {ChartsActivationEvent} event The event recorded on the `<svg/>` element.
|
|
38
40
|
* @param {null | ChartsAxisData} data The data about the clicked axis and items associated with it.
|
|
39
41
|
*/
|
|
40
|
-
onAxisClick?: (event:
|
|
42
|
+
onAxisClick?: (event: ChartsActivationEvent, data: null | ChartsAxisData) => void;
|
|
41
43
|
/**
|
|
42
44
|
* The function called when the pointer position corresponds to a new axis data item.
|
|
43
45
|
* This update can either be caused by a pointer movement, or an axis update.
|
|
@@ -106,6 +108,8 @@ export interface UseChartCartesianAxisState {
|
|
|
106
108
|
axesGap: number;
|
|
107
109
|
x: DefaultedXAxis[];
|
|
108
110
|
y: DefaultedYAxis[];
|
|
111
|
+
/** Only used to measure tick labels. Never merged into the rendered tick style. */
|
|
112
|
+
defaultTickLabelStyle?: ChartsTextStyle;
|
|
109
113
|
};
|
|
110
114
|
/**
|
|
111
115
|
* The controlled axis item highlighted.
|
|
@@ -5,6 +5,7 @@ export declare const selectorChartCartesianAxisState: (state: ChartState<[], [Us
|
|
|
5
5
|
axesGap: number;
|
|
6
6
|
x: DefaultedXAxis[];
|
|
7
7
|
y: DefaultedYAxis[];
|
|
8
|
+
defaultTickLabelStyle?: import("../../../getWordsByLines.mjs").ChartsTextStyle;
|
|
8
9
|
} | undefined;
|
|
9
10
|
export type SelectorChartRawXAxisType = <State extends ChartState<[], [UseChartCartesianAxisSignature]>>(state: State) => DefaultedXAxis[] | undefined;
|
|
10
11
|
export declare const selectorChartRawXAxis: SelectorChartRawXAxisType;
|
|
@@ -5,6 +5,7 @@ export declare const selectorChartCartesianAxisState: (state: ChartState<[], [Us
|
|
|
5
5
|
axesGap: number;
|
|
6
6
|
x: DefaultedXAxis[];
|
|
7
7
|
y: DefaultedYAxis[];
|
|
8
|
+
defaultTickLabelStyle?: import("../../../getWordsByLines.js").ChartsTextStyle;
|
|
8
9
|
} | undefined;
|
|
9
10
|
export type SelectorChartRawXAxisType = <State extends ChartState<[], [UseChartCartesianAxisSignature]>>(state: State) => DefaultedXAxis[] | undefined;
|
|
10
11
|
export declare const selectorChartRawXAxis: SelectorChartRawXAxisType;
|
package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js
CHANGED
|
@@ -20,6 +20,9 @@ var _useChartSeries2 = require("../../corePlugins/useChartSeries");
|
|
|
20
20
|
var _useChartCartesianAxisRendering = require("../useChartCartesianAxis/useChartCartesianAxisRendering.selectors");
|
|
21
21
|
var _getChartPoint = require("../../../getChartPoint");
|
|
22
22
|
var _getItemAtAxisPosition = require("./utils/getItemAtAxisPosition");
|
|
23
|
+
var _getItemAtRotationIndex = require("./utils/getItemAtRotationIndex");
|
|
24
|
+
var _useChartPolarAxis = require("../useChartPolarAxis/useChartPolarAxis.selectors");
|
|
25
|
+
var _useChartPolarInteraction = require("../useChartPolarAxis/useChartPolarInteraction.selectors");
|
|
23
26
|
var _itemActivation = require("./itemActivation");
|
|
24
27
|
var _useChartKeyboardNavigation = require("./useChartKeyboardNavigation.selectors");
|
|
25
28
|
/**
|
|
@@ -137,33 +140,63 @@ const useChartKeyboardNavigation = ({
|
|
|
137
140
|
});
|
|
138
141
|
|
|
139
142
|
/**
|
|
140
|
-
* The item a click landed on, read from the item the pointer is over.
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
+
* The item a click landed on, read from the item the pointer is over. An area or line path only
|
|
144
|
+
* knows its series, and a radar reports no item at all, so an incomplete one falls back to the
|
|
145
|
+
* axis under the pointer.
|
|
143
146
|
*
|
|
144
147
|
* A click that resolves nothing is left alone rather than focusing the chart. The drawing area
|
|
145
148
|
* is a rectangle, but the data rarely fills it: taking the focus from a click next to a pie,
|
|
146
149
|
* outside its circle, reads as the chart grabbing clicks that were not meant for it.
|
|
147
150
|
*/
|
|
148
151
|
const resolveItemAtPointer = (0, _useEventCallback.default)(event => {
|
|
149
|
-
|
|
152
|
+
const seriesConfig = (0, _useChartSeriesConfig.selectorChartSeriesConfig)(store.state);
|
|
150
153
|
const hoveredItem = store.state.interaction?.hoveredItem;
|
|
151
|
-
|
|
152
|
-
|
|
154
|
+
// Cleaned before the check, because what a series stores is not always an identifier: the
|
|
155
|
+
// scatter reports its whole data point, whose optional `id` would read as an incomplete one.
|
|
156
|
+
const cleanedHoveredItem = hoveredItem == null ? null : (0, _cleanIdentifier.cleanIdentifier)(seriesConfig, hoveredItem);
|
|
157
|
+
|
|
158
|
+
// Series that report a complete item need no further wiring.
|
|
159
|
+
if (cleanedHoveredItem != null && isCompleteFocusIdentifier(cleanedHoveredItem)) {
|
|
160
|
+
return cleanedHoveredItem;
|
|
153
161
|
}
|
|
154
162
|
const element = chartsLayerContainerRef.current;
|
|
155
163
|
const point = element === null ? null : (0, _getChartPoint.getChartPoint)(element, event);
|
|
156
|
-
|
|
164
|
+
if (!point || !instance.isPointInside?.(point.x, point.y)) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
const processedSeries = (0, _useChartSeries2.selectorChartSeriesProcessed)(store.state);
|
|
168
|
+
// An incomplete hovered item still names the series under the pointer, which is a better
|
|
169
|
+
// target than the focused one: a click on a series should stay on it.
|
|
170
|
+
const focusedItem = cleanedHoveredItem ?? store.state.keyboardNavigation.item;
|
|
171
|
+
const item = (0, _getItemAtAxisPosition.getItemAtAxisPosition)({
|
|
157
172
|
point,
|
|
158
173
|
xAxis: (0, _useChartCartesianAxisRendering.selectorChartXAxis)(store.state),
|
|
159
174
|
yAxis: (0, _useChartCartesianAxisRendering.selectorChartYAxis)(store.state),
|
|
160
|
-
processedSeries
|
|
161
|
-
focusedItem
|
|
162
|
-
})
|
|
163
|
-
|
|
175
|
+
processedSeries,
|
|
176
|
+
focusedItem
|
|
177
|
+
});
|
|
178
|
+
if (item !== null) {
|
|
179
|
+
return item;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// A radar area only covers the polygon the data draws, so a click inside the chart but outside
|
|
183
|
+
// it resolves nothing above. Fall back to the rotation axis, the same one the highlight uses.
|
|
184
|
+
if ((0, _useChartPolarAxis.selectorChartRotationAxis)(store.state).axisIds.length === 0) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return (0, _getItemAtRotationIndex.getItemAtRotationIndex)({
|
|
188
|
+
dataIndex: (0, _useChartPolarInteraction.selectorChartsInteractionRotationAxisIndex)(store.state),
|
|
189
|
+
processedSeries,
|
|
190
|
+
focusedItem
|
|
191
|
+
});
|
|
164
192
|
});
|
|
165
193
|
const activationRegistrationsRef = React.useRef(new Map());
|
|
166
194
|
const nextRegistrationIdRef = React.useRef(0);
|
|
195
|
+
const announceZoomChange = React.useCallback(() => {
|
|
196
|
+
store.set('keyboardNavigation', (0, _extends2.default)({}, store.state.keyboardNavigation, {
|
|
197
|
+
zoomAnnouncement: store.state.keyboardNavigation.zoomAnnouncement + 1
|
|
198
|
+
}));
|
|
199
|
+
}, [store]);
|
|
167
200
|
const registerItemActivationHandler = React.useCallback((scope, handler) => {
|
|
168
201
|
const registrationId = nextRegistrationIdRef.current;
|
|
169
202
|
nextRegistrationIdRef.current += 1;
|
|
@@ -191,10 +224,13 @@ const useChartKeyboardNavigation = ({
|
|
|
191
224
|
if (root && next !== null && root.contains(next)) {
|
|
192
225
|
return;
|
|
193
226
|
}
|
|
194
|
-
|
|
195
|
-
|
|
227
|
+
const keyboardNavigation = store.state.keyboardNavigation;
|
|
228
|
+
if (keyboardNavigation.isFocused || keyboardNavigation.zoomAnnouncement > 0) {
|
|
229
|
+
store.set('keyboardNavigation', (0, _extends2.default)({}, keyboardNavigation, {
|
|
196
230
|
isFocused: false,
|
|
197
|
-
isFocusVisible: false
|
|
231
|
+
isFocusVisible: false,
|
|
232
|
+
// The visible range is only announced while the user operates the chart.
|
|
233
|
+
zoomAnnouncement: 0
|
|
198
234
|
}));
|
|
199
235
|
}
|
|
200
236
|
}
|
|
@@ -240,6 +276,11 @@ const useChartKeyboardNavigation = ({
|
|
|
240
276
|
handler(event, focusedItem);
|
|
241
277
|
}
|
|
242
278
|
function keyboardHandler(event) {
|
|
279
|
+
// Item navigation only uses unmodified keys.
|
|
280
|
+
// Modified ones are left to the browser, and to chart interactions such as keyboard zoom and pan.
|
|
281
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
243
284
|
let newFocusedItem = store.state.keyboardNavigation.item;
|
|
244
285
|
const seriesConfig = (0, _useChartSeriesConfig.selectorChartSeriesConfig)(store.state);
|
|
245
286
|
let seriesType = newFocusedItem?.type;
|
|
@@ -312,7 +353,8 @@ const useChartKeyboardNavigation = ({
|
|
|
312
353
|
return {
|
|
313
354
|
instance: {
|
|
314
355
|
focusItem,
|
|
315
|
-
registerItemActivationHandler
|
|
356
|
+
registerItemActivationHandler,
|
|
357
|
+
announceZoomChange
|
|
316
358
|
}
|
|
317
359
|
};
|
|
318
360
|
};
|
|
@@ -322,7 +364,8 @@ useChartKeyboardNavigation.getInitialState = params => ({
|
|
|
322
364
|
item: null,
|
|
323
365
|
isFocused: false,
|
|
324
366
|
isFocusVisible: false,
|
|
325
|
-
enabled: !params.disableKeyboardNavigation
|
|
367
|
+
enabled: !params.disableKeyboardNavigation,
|
|
368
|
+
zoomAnnouncement: 0
|
|
326
369
|
}
|
|
327
370
|
});
|
|
328
371
|
useChartKeyboardNavigation.params = {
|
package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.mjs
CHANGED
|
@@ -13,6 +13,9 @@ import { selectorChartSeriesProcessed } from "../../corePlugins/useChartSeries/i
|
|
|
13
13
|
import { selectorChartXAxis, selectorChartYAxis } from "../useChartCartesianAxis/useChartCartesianAxisRendering.selectors.mjs";
|
|
14
14
|
import { getChartPoint } from "../../../getChartPoint.mjs";
|
|
15
15
|
import { getItemAtAxisPosition } from "./utils/getItemAtAxisPosition.mjs";
|
|
16
|
+
import { getItemAtRotationIndex } from "./utils/getItemAtRotationIndex.mjs";
|
|
17
|
+
import { selectorChartRotationAxis } from "../useChartPolarAxis/useChartPolarAxis.selectors.mjs";
|
|
18
|
+
import { selectorChartsInteractionRotationAxisIndex } from "../useChartPolarAxis/useChartPolarInteraction.selectors.mjs";
|
|
16
19
|
import { findItemActivationHandler, isItemActivationKey } from "./itemActivation.mjs";
|
|
17
20
|
import { selectorChartsIsFocusVisible, selectorChartsIsKeyboardActivationEnabled } from "./useChartKeyboardNavigation.selectors.mjs";
|
|
18
21
|
|
|
@@ -131,33 +134,63 @@ export const useChartKeyboardNavigation = ({
|
|
|
131
134
|
});
|
|
132
135
|
|
|
133
136
|
/**
|
|
134
|
-
* The item a click landed on, read from the item the pointer is over.
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
+
* The item a click landed on, read from the item the pointer is over. An area or line path only
|
|
138
|
+
* knows its series, and a radar reports no item at all, so an incomplete one falls back to the
|
|
139
|
+
* axis under the pointer.
|
|
137
140
|
*
|
|
138
141
|
* A click that resolves nothing is left alone rather than focusing the chart. The drawing area
|
|
139
142
|
* is a rectangle, but the data rarely fills it: taking the focus from a click next to a pie,
|
|
140
143
|
* outside its circle, reads as the chart grabbing clicks that were not meant for it.
|
|
141
144
|
*/
|
|
142
145
|
const resolveItemAtPointer = useEventCallback(event => {
|
|
143
|
-
|
|
146
|
+
const seriesConfig = selectorChartSeriesConfig(store.state);
|
|
144
147
|
const hoveredItem = store.state.interaction?.hoveredItem;
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
// Cleaned before the check, because what a series stores is not always an identifier: the
|
|
149
|
+
// scatter reports its whole data point, whose optional `id` would read as an incomplete one.
|
|
150
|
+
const cleanedHoveredItem = hoveredItem == null ? null : cleanIdentifier(seriesConfig, hoveredItem);
|
|
151
|
+
|
|
152
|
+
// Series that report a complete item need no further wiring.
|
|
153
|
+
if (cleanedHoveredItem != null && isCompleteFocusIdentifier(cleanedHoveredItem)) {
|
|
154
|
+
return cleanedHoveredItem;
|
|
147
155
|
}
|
|
148
156
|
const element = chartsLayerContainerRef.current;
|
|
149
157
|
const point = element === null ? null : getChartPoint(element, event);
|
|
150
|
-
|
|
158
|
+
if (!point || !instance.isPointInside?.(point.x, point.y)) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const processedSeries = selectorChartSeriesProcessed(store.state);
|
|
162
|
+
// An incomplete hovered item still names the series under the pointer, which is a better
|
|
163
|
+
// target than the focused one: a click on a series should stay on it.
|
|
164
|
+
const focusedItem = cleanedHoveredItem ?? store.state.keyboardNavigation.item;
|
|
165
|
+
const item = getItemAtAxisPosition({
|
|
151
166
|
point,
|
|
152
167
|
xAxis: selectorChartXAxis(store.state),
|
|
153
168
|
yAxis: selectorChartYAxis(store.state),
|
|
154
|
-
processedSeries
|
|
155
|
-
focusedItem
|
|
156
|
-
})
|
|
157
|
-
|
|
169
|
+
processedSeries,
|
|
170
|
+
focusedItem
|
|
171
|
+
});
|
|
172
|
+
if (item !== null) {
|
|
173
|
+
return item;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// A radar area only covers the polygon the data draws, so a click inside the chart but outside
|
|
177
|
+
// it resolves nothing above. Fall back to the rotation axis, the same one the highlight uses.
|
|
178
|
+
if (selectorChartRotationAxis(store.state).axisIds.length === 0) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return getItemAtRotationIndex({
|
|
182
|
+
dataIndex: selectorChartsInteractionRotationAxisIndex(store.state),
|
|
183
|
+
processedSeries,
|
|
184
|
+
focusedItem
|
|
185
|
+
});
|
|
158
186
|
});
|
|
159
187
|
const activationRegistrationsRef = React.useRef(new Map());
|
|
160
188
|
const nextRegistrationIdRef = React.useRef(0);
|
|
189
|
+
const announceZoomChange = React.useCallback(() => {
|
|
190
|
+
store.set('keyboardNavigation', _extends({}, store.state.keyboardNavigation, {
|
|
191
|
+
zoomAnnouncement: store.state.keyboardNavigation.zoomAnnouncement + 1
|
|
192
|
+
}));
|
|
193
|
+
}, [store]);
|
|
161
194
|
const registerItemActivationHandler = React.useCallback((scope, handler) => {
|
|
162
195
|
const registrationId = nextRegistrationIdRef.current;
|
|
163
196
|
nextRegistrationIdRef.current += 1;
|
|
@@ -185,10 +218,13 @@ export const useChartKeyboardNavigation = ({
|
|
|
185
218
|
if (root && next !== null && root.contains(next)) {
|
|
186
219
|
return;
|
|
187
220
|
}
|
|
188
|
-
|
|
189
|
-
|
|
221
|
+
const keyboardNavigation = store.state.keyboardNavigation;
|
|
222
|
+
if (keyboardNavigation.isFocused || keyboardNavigation.zoomAnnouncement > 0) {
|
|
223
|
+
store.set('keyboardNavigation', _extends({}, keyboardNavigation, {
|
|
190
224
|
isFocused: false,
|
|
191
|
-
isFocusVisible: false
|
|
225
|
+
isFocusVisible: false,
|
|
226
|
+
// The visible range is only announced while the user operates the chart.
|
|
227
|
+
zoomAnnouncement: 0
|
|
192
228
|
}));
|
|
193
229
|
}
|
|
194
230
|
}
|
|
@@ -234,6 +270,11 @@ export const useChartKeyboardNavigation = ({
|
|
|
234
270
|
handler(event, focusedItem);
|
|
235
271
|
}
|
|
236
272
|
function keyboardHandler(event) {
|
|
273
|
+
// Item navigation only uses unmodified keys.
|
|
274
|
+
// Modified ones are left to the browser, and to chart interactions such as keyboard zoom and pan.
|
|
275
|
+
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
237
278
|
let newFocusedItem = store.state.keyboardNavigation.item;
|
|
238
279
|
const seriesConfig = selectorChartSeriesConfig(store.state);
|
|
239
280
|
let seriesType = newFocusedItem?.type;
|
|
@@ -306,7 +347,8 @@ export const useChartKeyboardNavigation = ({
|
|
|
306
347
|
return {
|
|
307
348
|
instance: {
|
|
308
349
|
focusItem,
|
|
309
|
-
registerItemActivationHandler
|
|
350
|
+
registerItemActivationHandler,
|
|
351
|
+
announceZoomChange
|
|
310
352
|
}
|
|
311
353
|
};
|
|
312
354
|
};
|
|
@@ -315,7 +357,8 @@ useChartKeyboardNavigation.getInitialState = params => ({
|
|
|
315
357
|
item: null,
|
|
316
358
|
isFocused: false,
|
|
317
359
|
isFocusVisible: false,
|
|
318
|
-
enabled: !params.disableKeyboardNavigation
|
|
360
|
+
enabled: !params.disableKeyboardNavigation,
|
|
361
|
+
zoomAnnouncement: 0
|
|
319
362
|
}
|
|
320
363
|
});
|
|
321
364
|
useChartKeyboardNavigation.params = {
|
|
@@ -20,6 +20,9 @@ export declare const selectorChartsFocusedItem: (args_0: import("../../corePlugi
|
|
|
20
20
|
export declare const selectorChartsFocusedOrToFocusedItem: (args_0: import("../../corePlugins/useChartId/useChartId.types.mjs").UseChartIdState & import("../../corePlugins/useChartSeriesConfig/useChartSeriesConfig.types.mjs").UseChartSeriesConfigState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartExperimentalFeature/useChartExperimentalFeature.types.mjs").UseChartExperimentalFeaturesState & import("../../corePlugins/useChartDimensions/useChartDimensions.types.mjs").UseChartDimensionsState & import("../../corePlugins/useChartSeries/useChartSeries.types.mjs").UseChartSeriesState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartAnimation/useChartAnimation.types.mjs").UseChartAnimationState & import("../../../index.mjs").UseChartInteractionListenerState & Partial<import("./useChartKeyboardNavigation.types.mjs").UseChartKeyboardNavigationState> & {
|
|
21
21
|
cacheKey: import("../../models/index.mjs").ChartStateCacheKey;
|
|
22
22
|
}) => FocusedItemIdentifier<keyof import("../../../index.mjs").ChartsSeriesConfig> | null;
|
|
23
|
+
export declare const selectorChartsZoomAnnouncement: (args_0: import("../../corePlugins/useChartId/useChartId.types.mjs").UseChartIdState & import("../../corePlugins/useChartSeriesConfig/useChartSeriesConfig.types.mjs").UseChartSeriesConfigState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartExperimentalFeature/useChartExperimentalFeature.types.mjs").UseChartExperimentalFeaturesState & import("../../corePlugins/useChartDimensions/useChartDimensions.types.mjs").UseChartDimensionsState & import("../../corePlugins/useChartSeries/useChartSeries.types.mjs").UseChartSeriesState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartAnimation/useChartAnimation.types.mjs").UseChartAnimationState & import("../../../index.mjs").UseChartInteractionListenerState & Partial<import("./useChartKeyboardNavigation.types.mjs").UseChartKeyboardNavigationState> & {
|
|
24
|
+
cacheKey: import("../../models/index.mjs").ChartStateCacheKey;
|
|
25
|
+
}) => number;
|
|
23
26
|
export declare const selectorChartsIsKeyboardNavigationEnabled: (args_0: import("../../corePlugins/useChartId/useChartId.types.mjs").UseChartIdState & import("../../corePlugins/useChartSeriesConfig/useChartSeriesConfig.types.mjs").UseChartSeriesConfigState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartExperimentalFeature/useChartExperimentalFeature.types.mjs").UseChartExperimentalFeaturesState & import("../../corePlugins/useChartDimensions/useChartDimensions.types.mjs").UseChartDimensionsState & import("../../corePlugins/useChartSeries/useChartSeries.types.mjs").UseChartSeriesState<keyof import("../../../index.mjs").ChartsSeriesConfig> & import("../../corePlugins/useChartAnimation/useChartAnimation.types.mjs").UseChartAnimationState & import("../../../index.mjs").UseChartInteractionListenerState & Partial<import("./useChartKeyboardNavigation.types.mjs").UseChartKeyboardNavigationState> & {
|
|
24
27
|
cacheKey: import("../../models/index.mjs").ChartStateCacheKey;
|
|
25
28
|
}) => boolean;
|