@mui/x-charts
Version:
The community edition of MUI X Charts components.
74 lines (72 loc) • 2.5 kB
JavaScript
'use client';
import * as React from 'react';
import useEventCallback from '@mui/utils/useEventCallback';
import { useSvgRef } from "../../../../hooks/index.js";
import { useStore } from "../../../store/useStore.js";
import { useChartContext } from "../../../../context/ChartProvider/index.js";
import { getSVGPoint } from "../../../getSVGPoint.js";
/**
* Hook to get pointer interaction props for chart items.
*/
export function useRegisterPointerInteractions(getItemAtPosition, onItemEnter, onItemLeave) {
const {
instance
} = useChartContext();
const svgRef = useSvgRef();
const store = useStore();
const interactionActive = React.useRef(false);
const lastItemRef = React.useRef(undefined);
const onItemEnterRef = useEventCallback(() => onItemEnter?.());
const onItemLeaveRef = useEventCallback(() => onItemLeave?.());
React.useEffect(() => {
const svg = svgRef.current;
if (!svg) {
return undefined;
}
function onPointerEnter() {
interactionActive.current = true;
}
function reset() {
const lastItem = lastItemRef.current;
if (lastItem) {
lastItemRef.current = undefined;
instance.removeTooltipItem(lastItem);
instance.clearHighlight();
onItemLeaveRef();
}
}
function onPointerLeave() {
interactionActive.current = false;
reset();
}
const onPointerMove = function onPointerMove(event) {
const svgPoint = getSVGPoint(svg, event);
if (!instance.isPointInside(svgPoint.x, svgPoint.y)) {
reset();
return;
}
const item = getItemAtPosition(store.state, svgPoint);
if (item) {
instance.setLastUpdateSource('pointer');
instance.setTooltipItem(item);
instance.setHighlight(item);
onItemEnterRef();
lastItemRef.current = item;
} else {
reset();
}
};
svg.addEventListener('pointerleave', onPointerLeave);
svg.addEventListener('pointermove', onPointerMove);
svg.addEventListener('pointerenter', onPointerEnter);
return () => {
svg.removeEventListener('pointerenter', onPointerEnter);
svg.removeEventListener('pointermove', onPointerMove);
svg.removeEventListener('pointerleave', onPointerLeave);
/* Clean up state if this item is unmounted while active. */
if (interactionActive.current) {
onPointerLeave();
}
};
}, [getItemAtPosition, instance, onItemEnterRef, onItemLeaveRef, store, svgRef]);
}