Skip to content

Commit

Permalink
Use isPointInside function for both graphs and axis (#14222)
Browse files Browse the repository at this point in the history
  • Loading branch information
JCQuintas authored Aug 19, 2024
1 parent 60dc904 commit b217a27
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
7 changes: 3 additions & 4 deletions packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function ChartsXAxis(inProps: ChartsXAxisProps) {

const theme = useTheme();
const classes = useUtilityClasses({ ...defaultizedProps, theme });
const { left, top, width, height } = useDrawingArea();
const { left, top, width, height, isPointInside } = useDrawingArea();

const tickSize = disableTicks ? 4 : tickSizeProp;

Expand Down Expand Up @@ -217,9 +217,8 @@ function ChartsXAxis(inProps: ChartsXAxisProps) {
const xTickLabel = labelOffset ?? 0;
const yTickLabel = positionSign * (tickSize + 3);

const showTick = offset >= left - 1 && offset <= left + width + 1;
const showTickLabel =
offset + xTickLabel >= left - 1 && offset + xTickLabel <= left + width + 1;
const showTick = isPointInside({ x: offset, y: -1 }, { direction: 'x' });
const showTickLabel = isPointInside({ x: offset + xTickLabel, y: -1 }, { direction: 'x' });
return (
<g key={index} transform={`translate(${offset}, 0)`} className={classes.tickContainer}>
{!disableTicks && showTick && (
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) {

const classes = useUtilityClasses({ ...defaultizedProps, theme });

const { left, top, width, height } = useDrawingArea();
const { left, top, width, height, isPointInside } = useDrawingArea();

const tickSize = disableTicks ? 4 : tickSizeProp;

Expand Down Expand Up @@ -171,7 +171,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) {
const skipLabel =
typeof tickLabelInterval === 'function' && !tickLabelInterval?.(value, index);

const showLabel = offset >= top - 1 && offset <= height + top + 1;
const showLabel = isPointInside({ x: -1, y: offset }, { direction: 'y' });

if (!showLabel) {
return null;
Expand Down
35 changes: 25 additions & 10 deletions packages/x-charts/src/context/DrawingProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ export type DrawingArea = {
* @param {Object} point The point to check.
* @param {number} point.x The x coordinate of the point.
* @param {number} point.y The y coordinate of the point.
* @param {Element} targetElement The target element if relevant.
* @param {Object} options The options of the check.
* @param {Element} [options.targetElement] The element to check if it is allowed to overflow the drawing area.
* @param {'x' | 'y'} [options.direction] The direction to check.
* @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise.
*/
isPointInside: (point: { x: number; y: number }, targetElement?: Element) => boolean;
isPointInside: (
point: { x: number; y: number },
options?: {
targetElement?: Element;
direction?: 'x' | 'y';
},
) => boolean;
};

export const DrawingContext = React.createContext<
Expand Down Expand Up @@ -87,17 +95,24 @@ export function DrawingProvider(props: DrawingProviderProps) {
const chartId = useId();

const isPointInside = React.useCallback<DrawingArea['isPointInside']>(
({ x, y }, targetElement) => {
({ x, y }, options) => {
// For element allowed to overflow, wrapping them in <g data-drawing-container /> make them fully part of the drawing area.
if (targetElement && targetElement.closest('[data-drawing-container]')) {
if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) {
return true;
}
return (
x >= drawingArea.left &&
x <= drawingArea.left + drawingArea.width &&
y >= drawingArea.top &&
y <= drawingArea.top + drawingArea.height
);

const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width;
const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height;

if (options?.direction === 'x') {
return isInsideX;
}

if (options?.direction === 'y') {
return isInsideY;
}

return isInsideX && isInsideY;
},
[drawingArea],
);
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/hooks/useAxisEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => {
mousePosition.current.x = svgPoint.x;
mousePosition.current.y = svgPoint.y;

if (!drawingArea.isPointInside(svgPoint, event.target as SVGElement)) {
if (!drawingArea.isPointInside(svgPoint, { targetElement: event.target as SVGElement })) {
if (mousePosition.current.isInChart) {
dispatch({ type: 'exitChart' });
mousePosition.current.isInChart = false;
Expand Down

0 comments on commit b217a27

Please sign in to comment.