Skip to content

Commit ac80343

Browse files
CopilotJCQuintasalexfauquette
authored
[charts] Remove deprecated useAxisTooltip in favor of useAxesTooltip (mui#20962)
Signed-off-by: Jose C Quintas Jr <juniorquintas@gmail.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jose Quintas <juniorquintas@gmail.com> Co-authored-by: alex <alex.fauquette@gmail.com> Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
1 parent 599a331 commit ac80343

File tree

18 files changed

+554
-396
lines changed

18 files changed

+554
-396
lines changed

docs/data/migration/migration-charts-v8/migration-charts-v8.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,36 @@ useBarSeries(['id-1']); // Returns [{ id: "id-1", ... }]
135135
useBarSeries([]); // Returns []
136136
```
137137

138+
### Rename `useAxisTooltip` hook
139+
140+
The `useAxisTooltip` hook has been renamed to `useAxesTooltip` to better reflect its functionality of handling multiple axes.
141+
142+
The hook now always returns an array of tooltip data (one entry per active axis) instead of a single object.
143+
144+
```diff
145+
-import { useAxisTooltip, UseAxisTooltipReturnValue, UseAxisTooltipParams } from '@mui/x-charts';
146+
+import { useAxesTooltip, UseAxesTooltipReturnValue, UseAxesTooltipParams } from '@mui/x-charts';
147+
```
148+
149+
Run the following command to do the renaming.
150+
151+
```bash
152+
npx @mui/x-codemod@next v9.0.0/charts/rename-axis-tooltip-hook <path|folder>
153+
```
154+
155+
After running the codemod make sure to adapt the hook returned value to your needs.
156+
157+
```diff
158+
function CustomTooltip() {
159+
// If you want to keep only one axis
160+
- const tooltipData = useAxisTooltip();
161+
+ const tooltipData = useAxesTooltip()[0] ?? null;
162+
// If you use all the axes
163+
- const tooltipData = useAxisTooltip({ multipleAxes: true });
164+
+ const tooltipData = useAxesTooltip();
165+
}
166+
```
167+
138168
## Heatmap
139169

140170
### `hideLegend` default value changed ✅

packages/x-charts/src/ChartsTooltip/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export * from './ChartsTooltipTable';
1111
export type { ItemTooltip } from '../internals/plugins/models/seriesConfig/tooltipGetter.types';
1212
export type { UseItemTooltipReturnValue, UseRadarItemTooltipReturnValue } from './useItemTooltip';
1313
export { useItemTooltip, useRadarItemTooltip } from './useItemTooltip';
14-
export * from './useAxisTooltip';
1514
export * from './useAxesTooltip';
1615

1716
export { useMouseTracker } from './utils';
Lines changed: 226 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,234 @@
11
'use client';
2+
import { useSeries } from '../hooks/useSeries';
3+
import { useColorProcessor } from '../internals/plugins/corePlugins/useChartSeries/useColorProcessor';
4+
import { type SeriesId } from '../models/seriesType/common';
25
import {
3-
useAxisTooltip,
4-
type UseAxisTooltipParams,
5-
type UseAxisTooltipReturnValue,
6-
} from './useAxisTooltip';
6+
type CartesianChartSeriesType,
7+
type ChartsSeriesConfig,
8+
type PolarChartSeriesType,
9+
} from '../models/seriesType/config';
10+
import { type ComputedAxis, type PolarAxisDefaultized, type AxisId } from '../models/axis';
11+
import { useStore } from '../internals/store/useStore';
12+
import { getLabel } from '../internals/getLabel';
13+
import { isCartesianSeriesType } from '../internals/isCartesian';
14+
import { utcFormatter } from './utils';
15+
import {
16+
useRotationAxes,
17+
useRotationAxis,
18+
useXAxes,
19+
useXAxis,
20+
useYAxes,
21+
useYAxis,
22+
} from '../hooks/useAxis';
23+
import { useZAxes } from '../hooks/useZAxis';
24+
import {
25+
selectorChartsInteractionTooltipXAxes,
26+
selectorChartsInteractionTooltipYAxes,
27+
type UseChartCartesianAxisSignature,
28+
} from '../internals/plugins/featurePlugins/useChartCartesianAxis';
29+
import { type ChartsLabelMarkProps } from '../ChartsLabel';
30+
import { selectorChartsInteractionTooltipRotationAxes } from '../internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarInteraction.selectors';
31+
import { isPolarSeriesType } from '../internals/isPolar';
32+
33+
export interface UseAxesTooltipReturnValue<
34+
SeriesT extends CartesianChartSeriesType | PolarChartSeriesType =
35+
| CartesianChartSeriesType
36+
| PolarChartSeriesType,
37+
AxisValueT extends string | number | Date = string | number | Date,
38+
> {
39+
axisDirection: SeriesT extends CartesianChartSeriesType ? 'x' | 'y' : 'rotation' | 'radius';
40+
mainAxis: SeriesT extends CartesianChartSeriesType ? ComputedAxis : PolarAxisDefaultized;
41+
axisId: AxisId;
42+
axisValue: AxisValueT;
43+
axisFormattedValue: string;
44+
dataIndex: number;
45+
seriesItems: SeriesItem<SeriesT>[];
46+
}
47+
48+
export interface UseAxesTooltipParams {
49+
/**
50+
* The axis directions to consider.
51+
* If not defined, all directions are considered
52+
*/
53+
directions?: ('x' | 'y' | 'rotation')[];
54+
}
55+
56+
interface SeriesItem<T extends CartesianChartSeriesType | PolarChartSeriesType> {
57+
seriesId: SeriesId;
58+
color: string;
59+
value: ChartsSeriesConfig[T]['valueType'];
60+
formattedValue: string;
61+
formattedLabel: string | null;
62+
markType: ChartsLabelMarkProps['type'];
63+
}
64+
65+
function defaultAxisTooltipConfig(
66+
axis: ComputedAxis | PolarAxisDefaultized,
67+
dataIndex: number,
68+
axisDirection: 'x' | 'y' | 'rotation',
69+
): UseAxesTooltipReturnValue {
70+
const axisValue = axis.data?.[dataIndex] ?? null;
771

8-
type UseAxesTooltipParams = Omit<UseAxisTooltipParams, 'multipleAxes'>;
72+
const axisFormatter =
73+
axis.valueFormatter ??
74+
((v: string | number | Date) =>
75+
axis.scaleType === 'utc' ? utcFormatter(v) : v.toLocaleString());
76+
77+
const axisFormattedValue = axisFormatter(axisValue, {
78+
location: 'tooltip',
79+
scale: axis.scale,
80+
});
81+
82+
return {
83+
axisDirection,
84+
axisId: axis.id,
85+
mainAxis: axis,
86+
dataIndex,
87+
axisValue,
88+
axisFormattedValue,
89+
seriesItems: [],
90+
};
91+
}
992

1093
/**
1194
* Returns the axes to display in the tooltip and the series item related to them.
1295
*/
13-
export function useAxesTooltip(params?: UseAxesTooltipParams): UseAxisTooltipReturnValue[] | null {
14-
return useAxisTooltip({ ...params, multipleAxes: true });
96+
export function useAxesTooltip(params?: UseAxesTooltipParams): UseAxesTooltipReturnValue[] | null {
97+
const { directions } = params ?? {};
98+
99+
const defaultXAxis = useXAxis();
100+
const defaultYAxis = useYAxis();
101+
const defaultRotationAxis = useRotationAxis();
102+
103+
const store = useStore<[UseChartCartesianAxisSignature]>();
104+
105+
const tooltipXAxes = store.use(selectorChartsInteractionTooltipXAxes);
106+
const tooltipYAxes = store.use(selectorChartsInteractionTooltipYAxes);
107+
108+
const tooltipRotationAxes = store.use(selectorChartsInteractionTooltipRotationAxes);
109+
110+
const series = useSeries();
111+
112+
const { xAxis } = useXAxes();
113+
const { yAxis } = useYAxes();
114+
const { zAxis, zAxisIds } = useZAxes();
115+
116+
const { rotationAxis } = useRotationAxes();
117+
118+
const colorProcessors = useColorProcessor();
119+
120+
if (tooltipXAxes.length === 0 && tooltipYAxes.length === 0 && tooltipRotationAxes.length === 0) {
121+
return null;
122+
}
123+
124+
const tooltipAxes: UseAxesTooltipReturnValue[] = [];
125+
126+
if (directions === undefined || directions.includes('x')) {
127+
tooltipXAxes.forEach(({ axisId, dataIndex }) => {
128+
tooltipAxes.push(defaultAxisTooltipConfig(xAxis[axisId], dataIndex, 'x'));
129+
});
130+
}
131+
132+
if (directions === undefined || directions.includes('y')) {
133+
tooltipYAxes.forEach(({ axisId, dataIndex }) => {
134+
tooltipAxes.push(defaultAxisTooltipConfig(yAxis[axisId], dataIndex, 'y'));
135+
});
136+
}
137+
138+
if (directions === undefined || directions.includes('rotation')) {
139+
tooltipRotationAxes.forEach(({ axisId, dataIndex }) => {
140+
tooltipAxes.push(defaultAxisTooltipConfig(rotationAxis[axisId], dataIndex, 'rotation'));
141+
});
142+
}
143+
144+
Object.keys(series)
145+
.filter(isCartesianSeriesType)
146+
.forEach(<SeriesT extends CartesianChartSeriesType>(seriesType: SeriesT) => {
147+
const seriesOfType = series[seriesType];
148+
if (!seriesOfType) {
149+
return [];
150+
}
151+
return seriesOfType.seriesOrder.forEach((seriesId) => {
152+
const seriesToAdd = seriesOfType.series[seriesId]!;
153+
154+
const providedXAxisId = seriesToAdd.xAxisId ?? defaultXAxis.id;
155+
const providedYAxisId = seriesToAdd.yAxisId ?? defaultYAxis.id;
156+
157+
const tooltipItemIndex = tooltipAxes.findIndex(
158+
({ axisDirection, axisId }) =>
159+
(axisDirection === 'x' && axisId === providedXAxisId) ||
160+
(axisDirection === 'y' && axisId === providedYAxisId),
161+
);
162+
// Test if the series uses the default axis
163+
if (tooltipItemIndex >= 0) {
164+
const zAxisId = 'zAxisId' in seriesToAdd ? seriesToAdd.zAxisId : zAxisIds[0];
165+
const { dataIndex } = tooltipAxes[tooltipItemIndex];
166+
const color =
167+
colorProcessors[seriesType]?.(
168+
seriesToAdd,
169+
xAxis[providedXAxisId],
170+
yAxis[providedYAxisId],
171+
zAxisId ? zAxis[zAxisId] : undefined,
172+
)(dataIndex) ?? '';
173+
174+
const value = seriesToAdd.data[dataIndex] ?? null;
175+
const formattedValue = (seriesToAdd.valueFormatter as any)(value, {
176+
dataIndex,
177+
});
178+
const formattedLabel = getLabel(seriesToAdd.label, 'tooltip') ?? null;
179+
180+
tooltipAxes[tooltipItemIndex].seriesItems.push({
181+
seriesId,
182+
color,
183+
value,
184+
formattedValue,
185+
formattedLabel,
186+
markType: seriesToAdd.labelMarkType,
187+
});
188+
}
189+
});
190+
});
191+
192+
Object.keys(series)
193+
.filter(isPolarSeriesType)
194+
.forEach(<SeriesT extends PolarChartSeriesType>(seriesType: SeriesT) => {
195+
const seriesOfType = series[seriesType];
196+
if (!seriesOfType) {
197+
return [];
198+
}
199+
return seriesOfType.seriesOrder.forEach((seriesId) => {
200+
const seriesToAdd = seriesOfType.series[seriesId]!;
201+
202+
const providedRotationAxisId: AxisId | undefined =
203+
// @ts-expect-error Should be fixed when we introduce a polar series with a rotationAxisId
204+
seriesToAdd.rotationAxisId ?? defaultRotationAxis?.id;
205+
206+
const tooltipItemIndex = tooltipAxes.findIndex(
207+
({ axisDirection, axisId }) =>
208+
axisDirection === 'rotation' && axisId === providedRotationAxisId,
209+
);
210+
// Test if the series uses the default axis
211+
if (tooltipItemIndex >= 0) {
212+
const { dataIndex } = tooltipAxes[tooltipItemIndex];
213+
const color = colorProcessors[seriesType]?.(seriesToAdd)(dataIndex) ?? '';
214+
215+
const value = seriesToAdd.data[dataIndex] ?? null;
216+
const formattedValue = (seriesToAdd.valueFormatter as any)(value, {
217+
dataIndex,
218+
});
219+
const formattedLabel = getLabel(seriesToAdd.label, 'tooltip') ?? null;
220+
221+
tooltipAxes[tooltipItemIndex].seriesItems.push({
222+
seriesId,
223+
color,
224+
value,
225+
formattedValue,
226+
formattedLabel,
227+
markType: seriesToAdd.labelMarkType,
228+
});
229+
}
230+
});
231+
});
232+
233+
return tooltipAxes;
15234
}

0 commit comments

Comments
 (0)