Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions src/charts/lineChart/fragments/__tests__/lineChartPath.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,45 @@ describe('LineChartPath', () => {
const nodeElement = container.querySelector('[aria-label*="Data point 1: testKey"]');
expect(nodeElement).toBeInTheDocument();
});

describe('lineIndicator boundary constraints', () => {
const lineIndicatorConfig = {
lineIndicator: { stroke: 'red', strokeWidth: 1 },
};

it('should constrain lineIndicator within xAxisCoordinates boundaries', () => {
const testCases = [
{ description: 'left of boundary', shouldRender: false, x1: 50, x2: 400, xCursor: 40 },
{ description: 'at min boundary', shouldRender: true, x1: 50, x2: 400, xCursor: 50 },
{ description: 'within boundary', shouldRender: true, x1: 50, x2: 400, xCursor: 200 },
{ description: 'at max boundary', shouldRender: true, x1: 50, x2: 400, xCursor: 400 },
{ description: 'right of boundary', shouldRender: false, x1: 50, x2: 400, xCursor: 450 },
];

testCases.forEach(({ shouldRender, x1, x2, xCursor }) => {
const context = {
...CONTEXT,
xAxisCoordinates: {
...CONTEXT.xAxisCoordinates,
coordinates: { x1, x2, y1: 0, y2: 0 },
},
xCursor,
};

const { container } = render(
<LineChartContext.Provider value={context}>
<LineChart.Path dataKey="testKey" indicatorConfig={lineIndicatorConfig} />
</LineChartContext.Provider>
);

const lineIndicator = container.querySelector('line[class*="pointer-events-none"]');

if (shouldRender) {
expect(lineIndicator).toBeInTheDocument();
} else {
expect(lineIndicator).not.toBeInTheDocument();
}
});
});
});
});
14 changes: 10 additions & 4 deletions src/charts/lineChart/fragments/lineChartPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,15 @@ export const LineChartPath: FC<LineChartPathProps> = ({
const pressedRef = useRef<number | null>(null);
// the projection line logic
const { autoClick, lineIndicator, ...nodeIndicatorConfig } = indicatorConfig || {};
// line indicator <Y> coordinates
const y1 = context.extraSpaceTopY;
const y2 = Number(context.canvasHeight) - context.extraSpaceBottomY;

// Calculate line indicator boundaries using pre-calculated axis coordinates
// Y-axis: spans from top to bottom of chart area
const { y1, y2 } = yAxisCoordinates.coordinates;

// X-axis: constrain to path area to prevent overflow into axis labels
// The indicator should only render within the data visualization area
const { x1: pathAreaMinX, x2: pathAreaMaxX } = xAxisCoordinates.coordinates;
const isCursorWithinPathArea = context.xCursor >= pathAreaMinX && context.xCursor <= pathAreaMaxX;
// the path
const { tickValues: xTickValues } = xAxisCoordinates;
const { tickValues: yTickValues } = yAxisCoordinates;
Expand Down Expand Up @@ -193,7 +199,7 @@ export const LineChartPath: FC<LineChartPathProps> = ({
)}
{showIndicator && (
<>
{!!lineIndicator && (
{!!lineIndicator && isCursorWithinPathArea && (
<Line
{...lineIndicator}
className="pointer-events-none"
Expand Down
Loading