Skip to content

Commit

Permalink
[chart] Use default values instead of non-null assertion to prevent e…
Browse files Browse the repository at this point in the history
…rror being thrown (#13637)

Signed-off-by: Jose C Quintas Jr <[email protected]>
Co-authored-by: Alexandre Fauquette <[email protected]>
  • Loading branch information
JCQuintas and alexfauquette authored Jun 27, 2024
1 parent c523580 commit 8380f86
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 26 deletions.
32 changes: 28 additions & 4 deletions packages/x-charts/src/ChartsAxisHighlight/ChartsAxisHighlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,34 @@ function ChartsAxisHighlight(props: ChartsAxisHighlightProps) {

const getXPosition = getValueToPositionMapper(xScale);
const getYPosition = getValueToPositionMapper(yScale);

const axisX = axis.x;
const axisY = axis.y;

const isBandScaleX = xAxisHighlight === 'band' && axisX !== null && isBandScale(xScale);
const isBandScaleY = yAxisHighlight === 'band' && axisY !== null && isBandScale(yScale);

if (process.env.NODE_ENV !== 'production') {
const isXError = isBandScaleX && xScale(axisX.value) === undefined;
const isYError = isBandScaleY && yScale(axisY.value) === undefined;

if (isXError || isYError) {
console.error(
[
`MUI X Charts: The position value provided for the axis is not valid for the current scale.`,
`This probably means something is wrong with the data passed to the chart.`,
`The ChartsAxisHighlight component will not be displayed.`,
].join('\n'),
);
}
}

return (
<React.Fragment>
{xAxisHighlight === 'band' && axis.x !== null && isBandScale(xScale) && (
{isBandScaleX && xScale(axisX.value) !== undefined && (
<ChartsAxisHighlightPath
d={`M ${xScale(axis.x.value)! - (xScale.step() - xScale.bandwidth()) / 2} ${
// @ts-expect-error, xScale value is checked in the statement above
d={`M ${xScale(axisX.value) - (xScale.step() - xScale.bandwidth()) / 2} ${
yScale.range()[0]
} l ${xScale.step()} 0 l 0 ${
yScale.range()[1] - yScale.range()[0]
Expand All @@ -94,10 +117,11 @@ function ChartsAxisHighlight(props: ChartsAxisHighlightProps) {
/>
)}

{yAxisHighlight === 'band' && axis.y !== null && isBandScale(yScale) && (
{isBandScaleY && yScale(axisY.value) === undefined && (
<ChartsAxisHighlightPath
d={`M ${xScale.range()[0]} ${
yScale(axis.y.value)! - (yScale.step() - yScale.bandwidth()) / 2
// @ts-expect-error, yScale value is checked in the statement above
yScale(axisY.value) - (yScale.step() - yScale.bandwidth()) / 2
} l 0 ${yScale.step()} l ${
xScale.range()[1] - xScale.range()[0]
} 0 l 0 ${-yScale.step()} Z`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
import { InteractionContext } from '../context/InteractionProvider';
import { useCartesianContext } from '../context/CartesianProvider';
import { getValueToPositionMapper } from '../hooks/useScale';
import { getSVGPoint } from '../internals/utils';
import { getSVGPoint } from '../internals/getSVGPoint';
import { ScatterItemIdentifier } from '../models';
import { SeriesId } from '../models/seriesType/common';
import { useDrawingArea, useSvgRef } from '../hooks';
Expand Down
13 changes: 5 additions & 8 deletions packages/x-charts/src/hooks/useAxisEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { InteractionContext } from '../context/InteractionProvider';
import { useCartesianContext } from '../context/CartesianProvider';
import { isBandScale } from '../internals/isBandScale';
import { AxisDefaultized } from '../models/axis';
import { getSVGPoint } from '../internals/utils';
import { getSVGPoint } from '../internals/getSVGPoint';
import { useSvgRef } from './useSvgRef';
import { useDrawingArea } from './useDrawingArea';

Expand Down Expand Up @@ -31,10 +31,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => {
return () => {};
}

const getUpdate = (axisConfig: AxisDefaultized, mouseValue: number) => {
if (usedXAxis === null) {
return null;
}
function getNewAxisState(axisConfig: AxisDefaultized, mouseValue: number) {
const { scale, data: axisData, reverse } = axisConfig;

if (!isBandScale(scale)) {
Expand Down Expand Up @@ -93,7 +90,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => {
index: dataIndex,
value: axisData![dataIndex],
};
};
}

const handleOut = () => {
mousePosition.current = {
Expand All @@ -118,8 +115,8 @@ export const useAxisEvents = (disableAxisListener: boolean) => {
dispatch({ type: 'exitChart' });
return;
}
const newStateX = getUpdate(xAxis[usedXAxis], svgPoint.x);
const newStateY = getUpdate(yAxis[usedYAxis], svgPoint.y);
const newStateX = getNewAxisState(xAxis[usedXAxis], svgPoint.x);
const newStateY = getNewAxisState(yAxis[usedYAxis], svgPoint.y);

dispatch({ type: 'updateAxis', data: { x: newStateX, y: newStateY } });
};
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/hooks/useScale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AxisScaleConfig, D3Scale, ScaleName } from '../models/axis';
*/
export function getValueToPositionMapper(scale: D3Scale) {
if (isBandScale(scale)) {
return (value: any) => scale(value)! + scale.bandwidth() / 2;
return (value: any) => (scale(value) ?? 0) + scale.bandwidth() / 2;
}
return (value: any) => scale(value) as number;
}
Expand Down
11 changes: 11 additions & 0 deletions packages/x-charts/src/internals/getSVGPoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Transform mouse event position to coordinates inside the SVG.
* @param svg The SVG element
* @param event The mouseEvent to transform
*/
export function getSVGPoint(svg: SVGSVGElement, event: Pick<MouseEvent, 'clientX' | 'clientY'>) {
const pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
return pt.matrixTransform(svg.getScreenCTM()!.inverse());
}
2 changes: 2 additions & 0 deletions packages/x-charts/src/internals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from '../ResponsiveChartContainer/ResizableContainer';
// hooks
export { useReducedMotion } from '../hooks/useReducedMotion';
export { useSeries } from '../hooks/useSeries';
export { useDrawingArea } from '../hooks/useDrawingArea';
export { useChartContainerHooks } from '../ChartContainer/useChartContainerHooks';
export { useScatterChartProps } from '../ScatterChart/useScatterChartProps';
export { useLineChartProps } from '../LineChart/useLineChartProps';
Expand All @@ -15,6 +16,7 @@ export { useBarChartProps } from '../BarChart/useBarChartProps';
// utils
export * from './defaultizeValueFormatter';
export * from './configInit';
export * from './getSVGPoint';

// contexts

Expand Down
12 changes: 0 additions & 12 deletions packages/x-charts/src/internals/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@ export function getSymbol(shape: SymbolsTypes): number {
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
export type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;

/**
* Transform mouse event position to coordinates inside the SVG.
* @param svg The SVG element
* @param event The mouseEvent to transform
*/
export function getSVGPoint(svg: SVGSVGElement, event: Pick<MouseEvent, 'clientX' | 'clientY'>) {
const pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
return pt.matrixTransform(svg.getScreenCTM()!.inverse());
}

/**
* Helper that converts values and percentages into values.
* @param value The value provided by the developer. Can either be a number or a string with '%' or 'px'.
Expand Down

0 comments on commit 8380f86

Please sign in to comment.