-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChartsAxisHighlight.tsx
More file actions
165 lines (141 loc) · 5.54 KB
/
Copy pathChartsAxisHighlight.tsx
File metadata and controls
165 lines (141 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import * as React from 'react';
import PropTypes from 'prop-types';
import composeClasses from '@mui/utils/composeClasses';
import generateUtilityClass from '@mui/utils/generateUtilityClass';
import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
import { styled } from '@mui/material/styles';
import { InteractionContext } from '../context/InteractionProvider';
import { useCartesianContext } from '../context/CartesianProvider';
import { getValueToPositionMapper } from '../hooks/useScale';
import { isBandScale } from '../internals/isBandScale';
export interface ChartsAxisHighlightClasses {
/** Styles applied to the root element. */
root: string;
}
export type ChartsAxisHighlightClassKey = keyof ChartsAxisHighlightClasses;
export function getAxisHighlightUtilityClass(slot: string) {
return generateUtilityClass('MuiChartsAxisHighlight', slot);
}
export const chartsAxisHighlightClasses: ChartsAxisHighlightClasses = generateUtilityClasses(
'MuiChartsAxisHighlight',
['root'],
);
const useUtilityClasses = () => {
const slots = {
root: ['root'],
};
return composeClasses(slots, getAxisHighlightUtilityClass);
};
export const ChartsAxisHighlightPath = styled('path', {
name: 'MuiChartsAxisHighlight',
slot: 'Root',
overridesResolver: (_, styles) => styles.root,
})<{ ownerState: { axisHighlight: AxisHighlight } }>(({ ownerState, theme }) => ({
pointerEvents: 'none',
...(ownerState.axisHighlight === 'band' && {
fill: theme.palette.mode === 'light' ? 'gray' : 'white',
fillOpacity: 0.1,
}),
...(ownerState.axisHighlight === 'line' && {
strokeDasharray: '5 2',
stroke: theme.palette.mode === 'light' ? '#000000' : '#ffffff',
}),
}));
type AxisHighlight = 'none' | 'line' | 'band';
export type ChartsAxisHighlightProps = {
x?: AxisHighlight;
y?: AxisHighlight;
};
/**
* Demos:
*
* - [Custom components](https://mui.com/x/react-charts/components/)
*
* API:
*
* - [ChartsAxisHighlight API](https://mui.com/x/api/charts/charts-axis-highlight/)
*/
function ChartsAxisHighlight(props: ChartsAxisHighlightProps) {
const { x: xAxisHighlight, y: yAxisHighlight } = props;
const { xAxisIds, xAxis, yAxisIds, yAxis } = useCartesianContext();
const classes = useUtilityClasses();
const USED_X_AXIS_ID = xAxisIds[0];
const USED_Y_AXIS_ID = yAxisIds[0];
const xScale = xAxis[USED_X_AXIS_ID].scale;
const yScale = yAxis[USED_Y_AXIS_ID].scale;
const { axis } = React.useContext(InteractionContext);
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>
{isBandScaleX && xScale(axisX.value) !== undefined && (
<ChartsAxisHighlightPath
// @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]
} l ${-xScale.step()} 0 Z`}
className={classes.root}
ownerState={{ axisHighlight: 'band' }}
/>
)}
{isBandScaleY && yScale(axisY.value) === undefined && (
<ChartsAxisHighlightPath
d={`M ${xScale.range()[0]} ${
// @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`}
className={classes.root}
ownerState={{ axisHighlight: 'band' }}
/>
)}
{xAxisHighlight === 'line' && axis.x !== null && (
<ChartsAxisHighlightPath
d={`M ${getXPosition(axis.x.value)} ${yScale.range()[0]} L ${getXPosition(
axis.x.value,
)} ${yScale.range()[1]}`}
className={classes.root}
ownerState={{ axisHighlight: 'line' }}
/>
)}
{yAxisHighlight === 'line' && axis.y !== null && (
<ChartsAxisHighlightPath
d={`M ${xScale.range()[0]} ${getYPosition(axis.y.value)} L ${
xScale.range()[1]
} ${getYPosition(axis.y.value)}`}
className={classes.root}
ownerState={{ axisHighlight: 'line' }}
/>
)}
</React.Fragment>
);
}
ChartsAxisHighlight.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "pnpm proptypes" |
// ----------------------------------------------------------------------
x: PropTypes.oneOf(['band', 'line', 'none']),
y: PropTypes.oneOf(['band', 'line', 'none']),
} as any;
export { ChartsAxisHighlight };