@mui/x-charts
Version:
The community edition of MUI X Charts components.
109 lines (107 loc) • 4.01 kB
JavaScript
'use client';
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
import { selectorChartDefaultizedSeries } from "../../corePlugins/useChartSeries/useChartSeries.selectors.mjs";
import { selectorChartSeriesConfig } from "../../corePlugins/useChartSeriesConfig/index.mjs";
export const useChartKeyboardNavigation = ({
params,
store,
instance
}) => {
const {
chartsLayerContainerRef
} = instance;
React.useEffect(() => {
const element = chartsLayerContainerRef.current;
if (!element || params.disableKeyboardNavigation) {
return undefined;
}
function removeFocus(event) {
const root = event.currentTarget;
const next = event.relatedTarget;
// Avoid removing focus if we know it is moving to another children in the chart.
// This avoid extra computation ot remove/add focus at each keyboard pressed when navigating in the chart.
if (root && next instanceof Node && !root.contains(next)) {
if (store.state.keyboardNavigation.isFocused) {
store.set('keyboardNavigation', _extends({}, store.state.keyboardNavigation, {
isFocused: false
}));
}
}
}
function restoreFocus() {
if (!store.state.keyboardNavigation.isFocused) {
store.update(_extends({}, store.state.highlight && {
highlight: _extends({}, store.state.highlight, {
lastUpdate: 'keyboard'
})
}, store.state.interaction && {
interaction: _extends({}, store.state.interaction, {
lastUpdate: 'keyboard'
})
}, {
keyboardNavigation: _extends({}, store.state.keyboardNavigation, {
isFocused: true
})
}));
}
}
function keyboardHandler(event) {
let newFocusedItem = store.state.keyboardNavigation.item;
const seriesConfig = selectorChartSeriesConfig(store.state);
let seriesType = newFocusedItem?.type;
if (!seriesType) {
seriesType = Object.keys(selectorChartDefaultizedSeries(store.state)).find(key => seriesConfig[key] !== undefined);
if (seriesType === undefined) {
return;
}
}
const calculateFocusedItem = seriesConfig[seriesType]?.keyboardFocusHandler?.(event);
if (!calculateFocusedItem) {
return;
}
newFocusedItem = calculateFocusedItem(newFocusedItem, store.state);
if (newFocusedItem !== store.state.keyboardNavigation.item) {
event.preventDefault();
store.update(_extends({}, store.state.highlight && {
highlight: _extends({}, store.state.highlight, {
lastUpdate: 'keyboard'
})
}, store.state.interaction && {
interaction: _extends({}, store.state.interaction, {
lastUpdate: 'keyboard'
})
}, {
keyboardNavigation: _extends({}, store.state.keyboardNavigation, {
item: newFocusedItem
})
}));
}
}
element.addEventListener('keydown', keyboardHandler);
element.addEventListener('focusout', removeFocus);
element.addEventListener('focusin', restoreFocus);
return () => {
element.removeEventListener('keydown', keyboardHandler);
element.removeEventListener('focusout', removeFocus);
element.removeEventListener('focusin', restoreFocus);
};
}, [chartsLayerContainerRef, params.disableKeyboardNavigation, store]);
useEnhancedEffect(() => {
store.set('keyboardNavigation', _extends({}, store.state.keyboardNavigation, {
enabled: !params.disableKeyboardNavigation
}));
}, [store, params.disableKeyboardNavigation]);
return {};
};
useChartKeyboardNavigation.getInitialState = params => ({
keyboardNavigation: {
item: null,
isFocused: false,
enabled: !params.disableKeyboardNavigation
}
});
useChartKeyboardNavigation.params = {
disableKeyboardNavigation: true
};