@mui/x-charts 8.5.3 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BarChart/AnimatedBarElement.js +3 -1
- package/BarChart/BarLabel/BarLabelPlot.d.ts +2 -2
- package/BarChart/BarLabel/BarLabelPlot.js +33 -25
- package/BarChart/BarPlot.js +55 -40
- package/BarChart/barClasses.d.ts +12 -0
- package/BarChart/barClasses.js +25 -0
- package/BarChart/index.d.ts +3 -1
- package/BarChart/index.js +23 -1
- package/BarChart/types.d.ts +5 -1
- package/CHANGELOG.md +107 -0
- package/ChartsLegend/ChartsLegend.js +1 -0
- package/ChartsXAxis/ChartsXAxis.js +4 -108
- package/ChartsXAxis/getVisibleLabels.d.ts +14 -0
- package/ChartsXAxis/getVisibleLabels.js +71 -0
- package/ChartsXAxis/shortenLabels.d.ts +4 -0
- package/ChartsXAxis/shortenLabels.js +48 -0
- package/ChartsYAxis/ChartsYAxis.js +2 -39
- package/ChartsYAxis/shortenLabels.d.ts +4 -0
- package/ChartsYAxis/shortenLabels.js +46 -0
- package/LineChart/AnimatedArea.js +4 -1
- package/LineChart/AnimatedLine.js +4 -1
- package/LineChart/CircleMarkElement.js +4 -1
- package/LineChart/MarkElement.js +4 -1
- package/LineChart/MarkPlot.js +1 -0
- package/PieChart/PieArc.js +3 -1
- package/PieChart/PiePlot.js +6 -0
- package/PieChart/index.d.ts +3 -1
- package/PieChart/index.js +18 -1
- package/PieChart/pieClasses.d.ts +12 -0
- package/PieChart/pieClasses.js +24 -0
- package/Toolbar/ToolbarButton.js +2 -0
- package/esm/BarChart/AnimatedBarElement.js +3 -1
- package/esm/BarChart/BarLabel/BarLabelPlot.d.ts +2 -2
- package/esm/BarChart/BarLabel/BarLabelPlot.js +33 -25
- package/esm/BarChart/BarPlot.js +55 -40
- package/esm/BarChart/barClasses.d.ts +12 -0
- package/esm/BarChart/barClasses.js +15 -0
- package/esm/BarChart/index.d.ts +3 -1
- package/esm/BarChart/index.js +2 -1
- package/esm/BarChart/types.d.ts +5 -1
- package/esm/ChartsLegend/ChartsLegend.js +1 -0
- package/esm/ChartsXAxis/ChartsXAxis.js +2 -106
- package/esm/ChartsXAxis/getVisibleLabels.d.ts +14 -0
- package/esm/ChartsXAxis/getVisibleLabels.js +67 -0
- package/esm/ChartsXAxis/shortenLabels.d.ts +4 -0
- package/esm/ChartsXAxis/shortenLabels.js +42 -0
- package/esm/ChartsYAxis/ChartsYAxis.js +1 -38
- package/esm/ChartsYAxis/shortenLabels.d.ts +4 -0
- package/esm/ChartsYAxis/shortenLabels.js +41 -0
- package/esm/LineChart/AnimatedArea.js +4 -1
- package/esm/LineChart/AnimatedLine.js +4 -1
- package/esm/LineChart/CircleMarkElement.js +4 -1
- package/esm/LineChart/MarkElement.js +4 -1
- package/esm/LineChart/MarkPlot.js +1 -0
- package/esm/PieChart/PieArc.js +3 -1
- package/esm/PieChart/PiePlot.js +6 -0
- package/esm/PieChart/index.d.ts +3 -1
- package/esm/PieChart/index.js +2 -1
- package/esm/PieChart/pieClasses.d.ts +12 -0
- package/esm/PieChart/pieClasses.js +15 -0
- package/esm/Toolbar/ToolbarButton.js +2 -0
- package/esm/index.js +1 -1
- package/esm/internals/components/NotRendered.d.ts +9 -0
- package/esm/internals/components/NotRendered.js +10 -0
- package/esm/internals/index.d.ts +1 -0
- package/esm/internals/index.js +1 -0
- package/esm/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.js +30 -2
- package/esm/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.d.ts +8 -2
- package/esm/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.js +20 -4
- package/esm/locales/enUS.d.ts +3 -0
- package/esm/locales/enUS.js +8 -2
- package/esm/locales/frFR.d.ts +3 -0
- package/esm/locales/frFR.js +7 -0
- package/esm/locales/ptBR.d.ts +3 -0
- package/esm/locales/ptBR.js +7 -1
- package/esm/locales/ptPT.d.ts +3 -0
- package/esm/locales/ptPT.js +7 -1
- package/esm/locales/utils/chartsLocaleTextApi.d.ts +17 -0
- package/esm/locales/utils/getChartsLocalization.d.ts +3 -0
- package/esm/locales/utils/imageMimeTypes.d.ts +2 -0
- package/esm/locales/utils/imageMimeTypes.js +5 -0
- package/esm/models/slots/chartsBaseSlotProps.d.ts +4 -0
- package/index.js +1 -1
- package/internals/components/NotRendered.d.ts +9 -0
- package/internals/components/NotRendered.js +16 -0
- package/internals/index.d.ts +1 -0
- package/internals/index.js +12 -0
- package/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.js +30 -2
- package/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.d.ts +8 -2
- package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.js +20 -4
- package/locales/enUS.d.ts +3 -0
- package/locales/enUS.js +8 -2
- package/locales/frFR.d.ts +3 -0
- package/locales/frFR.js +7 -0
- package/locales/ptBR.d.ts +3 -0
- package/locales/ptBR.js +7 -1
- package/locales/ptPT.d.ts +3 -0
- package/locales/ptPT.js +7 -1
- package/locales/utils/chartsLocaleTextApi.d.ts +17 -0
- package/locales/utils/getChartsLocalization.d.ts +3 -0
- package/locales/utils/imageMimeTypes.d.ts +2 -0
- package/locales/utils/imageMimeTypes.js +11 -0
- package/models/slots/chartsBaseSlotProps.d.ts +4 -0
- package/package.json +2 -2
package/esm/BarChart/BarPlot.js
CHANGED
|
@@ -16,6 +16,7 @@ import { checkScaleErrors } from "./checkScaleErrors.js";
|
|
|
16
16
|
import { useBarSeriesContext } from "../hooks/useBarSeries.js";
|
|
17
17
|
import { useSkipAnimation } from "../hooks/useSkipAnimation.js";
|
|
18
18
|
import { useInternalIsZoomInteracting } from "../internals/plugins/featurePlugins/useChartCartesianAxis/useInternalIsZoomInteracting.js";
|
|
19
|
+
import { useUtilityClasses } from "./barClasses.js";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Solution of the equations
|
|
@@ -69,13 +70,13 @@ const useAggregatedData = () => {
|
|
|
69
70
|
const defaultYAxisId = yAxisIds[0];
|
|
70
71
|
const masks = {};
|
|
71
72
|
const data = stackingGroups.flatMap(({
|
|
72
|
-
ids:
|
|
73
|
+
ids: seriesIds
|
|
73
74
|
}, groupIndex) => {
|
|
74
75
|
const xMin = drawingArea.left;
|
|
75
76
|
const xMax = drawingArea.left + drawingArea.width;
|
|
76
77
|
const yMin = drawingArea.top;
|
|
77
78
|
const yMax = drawingArea.top + drawingArea.height;
|
|
78
|
-
return
|
|
79
|
+
return seriesIds.map(seriesId => {
|
|
79
80
|
const xAxisId = series[seriesId].xAxisId ?? defaultXAxisId;
|
|
80
81
|
const yAxisId = series[seriesId].yAxisId ?? defaultYAxisId;
|
|
81
82
|
const xAxisConfig = xAxis[xAxisId];
|
|
@@ -101,7 +102,7 @@ const useAggregatedData = () => {
|
|
|
101
102
|
data: currentSeriesData,
|
|
102
103
|
layout
|
|
103
104
|
} = series[seriesId];
|
|
104
|
-
|
|
105
|
+
const seriesDataPoints = baseScaleConfig.data.map((baseValue, dataIndex) => {
|
|
105
106
|
if (currentSeriesData[dataIndex] == null) {
|
|
106
107
|
return null;
|
|
107
108
|
}
|
|
@@ -150,6 +151,10 @@ const useAggregatedData = () => {
|
|
|
150
151
|
mask.hasPositive = mask.hasPositive || (result.value ?? 0) > 0;
|
|
151
152
|
return result;
|
|
152
153
|
}).filter(rectangle => rectangle !== null);
|
|
154
|
+
return {
|
|
155
|
+
seriesId,
|
|
156
|
+
data: seriesDataPoints
|
|
157
|
+
};
|
|
153
158
|
});
|
|
154
159
|
});
|
|
155
160
|
return {
|
|
@@ -192,7 +197,9 @@ function BarPlot(props) {
|
|
|
192
197
|
const isZoomInteracting = useInternalIsZoomInteracting();
|
|
193
198
|
const skipAnimation = useSkipAnimation(isZoomInteracting || inSkipAnimation);
|
|
194
199
|
const withoutBorderRadius = !borderRadius || borderRadius <= 0;
|
|
200
|
+
const classes = useUtilityClasses();
|
|
195
201
|
return /*#__PURE__*/_jsxs(BarPlotRoot, {
|
|
202
|
+
className: classes.root,
|
|
196
203
|
children: [!withoutBorderRadius && masksData.map(({
|
|
197
204
|
id,
|
|
198
205
|
x,
|
|
@@ -217,45 +224,53 @@ function BarPlot(props) {
|
|
|
217
224
|
}, id);
|
|
218
225
|
}), completedData.map(({
|
|
219
226
|
seriesId,
|
|
220
|
-
|
|
221
|
-
color,
|
|
222
|
-
maskId,
|
|
223
|
-
layout,
|
|
224
|
-
x,
|
|
225
|
-
xOrigin,
|
|
226
|
-
y,
|
|
227
|
-
yOrigin,
|
|
228
|
-
width,
|
|
229
|
-
height
|
|
227
|
+
data
|
|
230
228
|
}) => {
|
|
231
|
-
const barElement = /*#__PURE__*/_jsx(BarElement, _extends({
|
|
232
|
-
id: seriesId,
|
|
233
|
-
dataIndex: dataIndex,
|
|
234
|
-
color: color,
|
|
235
|
-
skipAnimation: skipAnimation ?? false,
|
|
236
|
-
layout: layout ?? 'vertical',
|
|
237
|
-
x: x,
|
|
238
|
-
xOrigin: xOrigin,
|
|
239
|
-
y: y,
|
|
240
|
-
yOrigin: yOrigin,
|
|
241
|
-
width: width,
|
|
242
|
-
height: height
|
|
243
|
-
}, other, {
|
|
244
|
-
onClick: onItemClick && (event => {
|
|
245
|
-
onItemClick(event, {
|
|
246
|
-
type: 'bar',
|
|
247
|
-
seriesId,
|
|
248
|
-
dataIndex
|
|
249
|
-
});
|
|
250
|
-
})
|
|
251
|
-
}), `${seriesId}-${dataIndex}`);
|
|
252
|
-
if (withoutBorderRadius) {
|
|
253
|
-
return barElement;
|
|
254
|
-
}
|
|
255
229
|
return /*#__PURE__*/_jsx("g", {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
230
|
+
"data-series": seriesId,
|
|
231
|
+
className: classes.series,
|
|
232
|
+
children: data.map(({
|
|
233
|
+
dataIndex,
|
|
234
|
+
color,
|
|
235
|
+
maskId,
|
|
236
|
+
layout,
|
|
237
|
+
x,
|
|
238
|
+
xOrigin,
|
|
239
|
+
y,
|
|
240
|
+
yOrigin,
|
|
241
|
+
width,
|
|
242
|
+
height
|
|
243
|
+
}) => {
|
|
244
|
+
const barElement = /*#__PURE__*/_jsx(BarElement, _extends({
|
|
245
|
+
id: seriesId,
|
|
246
|
+
dataIndex: dataIndex,
|
|
247
|
+
color: color,
|
|
248
|
+
skipAnimation: skipAnimation ?? false,
|
|
249
|
+
layout: layout ?? 'vertical',
|
|
250
|
+
x: x,
|
|
251
|
+
xOrigin: xOrigin,
|
|
252
|
+
y: y,
|
|
253
|
+
yOrigin: yOrigin,
|
|
254
|
+
width: width,
|
|
255
|
+
height: height
|
|
256
|
+
}, other, {
|
|
257
|
+
onClick: onItemClick && (event => {
|
|
258
|
+
onItemClick(event, {
|
|
259
|
+
type: 'bar',
|
|
260
|
+
seriesId,
|
|
261
|
+
dataIndex
|
|
262
|
+
});
|
|
263
|
+
})
|
|
264
|
+
}), dataIndex);
|
|
265
|
+
if (withoutBorderRadius) {
|
|
266
|
+
return barElement;
|
|
267
|
+
}
|
|
268
|
+
return /*#__PURE__*/_jsx("g", {
|
|
269
|
+
clipPath: `url(#${maskId})`,
|
|
270
|
+
children: barElement
|
|
271
|
+
}, dataIndex);
|
|
272
|
+
})
|
|
273
|
+
}, seriesId);
|
|
259
274
|
}), barLabel && /*#__PURE__*/_jsx(BarLabelPlot, _extends({
|
|
260
275
|
bars: completedData,
|
|
261
276
|
skipAnimation: skipAnimation,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface BarClasses {
|
|
2
|
+
/** Styles applied to the bar plot element. */
|
|
3
|
+
root: string;
|
|
4
|
+
/** Styles applied to the group surrounding a series' bar elements. */
|
|
5
|
+
series: string;
|
|
6
|
+
/** Styles applied to the group surrounding a series' labels. */
|
|
7
|
+
seriesLabels: string;
|
|
8
|
+
}
|
|
9
|
+
export type BarClassKey = keyof BarClasses;
|
|
10
|
+
export declare function getBarUtilityClass(slot: string): string;
|
|
11
|
+
export declare const barClasses: BarClasses;
|
|
12
|
+
export declare const useUtilityClasses: (classes?: Partial<BarClasses>) => Record<"root" | "series" | "seriesLabels", string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import generateUtilityClass from '@mui/utils/generateUtilityClass';
|
|
2
|
+
import composeClasses from '@mui/utils/composeClasses';
|
|
3
|
+
import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
|
|
4
|
+
export function getBarUtilityClass(slot) {
|
|
5
|
+
return generateUtilityClass('MuiBar', slot);
|
|
6
|
+
}
|
|
7
|
+
export const barClasses = generateUtilityClasses('MuiBar', ['root', 'series', 'seriesLabels']);
|
|
8
|
+
export const useUtilityClasses = classes => {
|
|
9
|
+
const slots = {
|
|
10
|
+
root: ['root'],
|
|
11
|
+
series: ['series'],
|
|
12
|
+
seriesLabels: ['seriesLabels']
|
|
13
|
+
};
|
|
14
|
+
return composeClasses(slots, getBarUtilityClass, classes);
|
|
15
|
+
};
|
package/esm/BarChart/index.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ export * from "./BarChart.js";
|
|
|
2
2
|
export * from "./BarPlot.js";
|
|
3
3
|
export * from "./BarElement.js";
|
|
4
4
|
export * from "./BarLabel/index.js";
|
|
5
|
-
export * from "./barElementClasses.js";
|
|
5
|
+
export * from "./barElementClasses.js";
|
|
6
|
+
export { barClasses, getBarUtilityClass } from "./barClasses.js";
|
|
7
|
+
export type { BarClassKey, BarClasses } from "./barClasses.js";
|
package/esm/BarChart/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export * from "./BarChart.js";
|
|
|
2
2
|
export * from "./BarPlot.js";
|
|
3
3
|
export * from "./BarElement.js";
|
|
4
4
|
export * from "./BarLabel/index.js";
|
|
5
|
-
export * from "./barElementClasses.js";
|
|
5
|
+
export * from "./barElementClasses.js";
|
|
6
|
+
export { barClasses, getBarUtilityClass } from "./barClasses.js";
|
package/esm/BarChart/types.d.ts
CHANGED
|
@@ -9,7 +9,11 @@ export type AnimationData = {
|
|
|
9
9
|
xOrigin: number;
|
|
10
10
|
layout: BarSeriesType['layout'];
|
|
11
11
|
};
|
|
12
|
-
export interface
|
|
12
|
+
export interface ProcessedBarSeriesData {
|
|
13
|
+
seriesId: SeriesId;
|
|
14
|
+
data: ProcessedBarData[];
|
|
15
|
+
}
|
|
16
|
+
export interface ProcessedBarData extends AnimationData {
|
|
13
17
|
seriesId: SeriesId;
|
|
14
18
|
dataIndex: number;
|
|
15
19
|
color: string;
|
|
@@ -81,6 +81,7 @@ const ChartsLegend = consumeSlots('MuiChartsLegend', 'legend', {
|
|
|
81
81
|
children: data.items.map((item, i) => {
|
|
82
82
|
return /*#__PURE__*/_jsx("li", {
|
|
83
83
|
className: classes?.item,
|
|
84
|
+
"data-series": item.id,
|
|
84
85
|
children: /*#__PURE__*/_jsxs(Element, {
|
|
85
86
|
className: classes?.series,
|
|
86
87
|
role: onItemClick ? 'button' : undefined,
|
|
@@ -9,24 +9,22 @@ import useSlotProps from '@mui/utils/useSlotProps';
|
|
|
9
9
|
import composeClasses from '@mui/utils/composeClasses';
|
|
10
10
|
import { useThemeProps, useTheme, styled } from '@mui/material/styles';
|
|
11
11
|
import { useRtl } from '@mui/system/RtlProvider';
|
|
12
|
-
import { clampAngle } from "../internals/clampAngle.js";
|
|
13
12
|
import { useIsHydrated } from "../hooks/useIsHydrated.js";
|
|
14
|
-
import { doesTextFitInRect, ellipsize } from "../internals/ellipsize.js";
|
|
15
13
|
import { getStringSize } from "../internals/domUtils.js";
|
|
16
14
|
import { useTicks } from "../hooks/useTicks.js";
|
|
17
15
|
import { getAxisUtilityClass } from "../ChartsAxis/axisClasses.js";
|
|
18
16
|
import { AxisRoot } from "../internals/components/AxisSharedComponents.js";
|
|
19
17
|
import { ChartsText } from "../ChartsText/index.js";
|
|
20
|
-
import { getMinXTranslation } from "../internals/geometry.js";
|
|
21
18
|
import { useMounted } from "../hooks/useMounted.js";
|
|
22
19
|
import { useDrawingArea } from "../hooks/useDrawingArea.js";
|
|
23
|
-
import { getWordsByLines } from "../internals/getWordsByLines.js";
|
|
24
20
|
import { isInfinity } from "../internals/isInfinity.js";
|
|
25
21
|
import { isBandScale } from "../internals/isBandScale.js";
|
|
26
22
|
import { useChartContext } from "../context/ChartProvider/useChartContext.js";
|
|
27
23
|
import { useXAxes } from "../hooks/useAxis.js";
|
|
28
24
|
import { getDefaultBaseline, getDefaultTextAnchor } from "../ChartsText/defaultTextPlacement.js";
|
|
29
25
|
import { invertTextAnchor } from "../internals/invertTextAnchor.js";
|
|
26
|
+
import { shortenLabels } from "./shortenLabels.js";
|
|
27
|
+
import { getVisibleLabels } from "./getVisibleLabels.js";
|
|
30
28
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
31
29
|
const useUtilityClasses = ownerState => {
|
|
32
30
|
const {
|
|
@@ -49,108 +47,6 @@ const useUtilityClasses = ownerState => {
|
|
|
49
47
|
const TICK_LABEL_GAP = 3;
|
|
50
48
|
/* Gap between the axis label and tick labels. */
|
|
51
49
|
const AXIS_LABEL_TICK_LABEL_GAP = 4;
|
|
52
|
-
|
|
53
|
-
/* Returns a set of indices of the tick labels that should be visible. */
|
|
54
|
-
function getVisibleLabels(xTicks, {
|
|
55
|
-
tickLabelStyle: style,
|
|
56
|
-
tickLabelInterval,
|
|
57
|
-
tickLabelMinGap,
|
|
58
|
-
reverse,
|
|
59
|
-
isMounted,
|
|
60
|
-
isXInside
|
|
61
|
-
}) {
|
|
62
|
-
const getTickLabelSize = tick => {
|
|
63
|
-
if (!isMounted || tick.formattedValue === undefined) {
|
|
64
|
-
return {
|
|
65
|
-
width: 0,
|
|
66
|
-
height: 0
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const tickSizes = getWordsByLines({
|
|
70
|
-
style,
|
|
71
|
-
needsComputation: true,
|
|
72
|
-
text: tick.formattedValue
|
|
73
|
-
});
|
|
74
|
-
return {
|
|
75
|
-
width: Math.max(...tickSizes.map(size => size.width)),
|
|
76
|
-
height: Math.max(tickSizes.length * tickSizes[0].height)
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
|
-
if (typeof tickLabelInterval === 'function') {
|
|
80
|
-
return new Set(xTicks.filter((item, index) => tickLabelInterval(item.value, index)));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Filter label to avoid overlap
|
|
84
|
-
let previousTextLimit = 0;
|
|
85
|
-
const direction = reverse ? -1 : 1;
|
|
86
|
-
return new Set(xTicks.filter((item, labelIndex) => {
|
|
87
|
-
const {
|
|
88
|
-
offset,
|
|
89
|
-
labelOffset
|
|
90
|
-
} = item;
|
|
91
|
-
const textPosition = offset + labelOffset;
|
|
92
|
-
if (labelIndex > 0 && direction * textPosition < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
if (!isXInside(textPosition)) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/* Measuring text width is expensive, so we need to delay it as much as possible to improve performance. */
|
|
100
|
-
const {
|
|
101
|
-
width,
|
|
102
|
-
height
|
|
103
|
-
} = getTickLabelSize(item);
|
|
104
|
-
const distance = getMinXTranslation(width, height, style?.angle);
|
|
105
|
-
const currentTextLimit = textPosition - direction * distance / 2;
|
|
106
|
-
if (labelIndex > 0 && direction * currentTextLimit < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
107
|
-
// Except for the first label, we skip all label that overlap with the last accepted.
|
|
108
|
-
// Notice that the early return prevents `previousTextLimit` from being updated.
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
previousTextLimit = textPosition + direction * distance / 2;
|
|
112
|
-
return true;
|
|
113
|
-
}));
|
|
114
|
-
}
|
|
115
|
-
function shortenLabels(visibleLabels, drawingArea, maxHeight, isRtl, tickLabelStyle) {
|
|
116
|
-
const shortenedLabels = new Map();
|
|
117
|
-
const angle = clampAngle(tickLabelStyle?.angle ?? 0);
|
|
118
|
-
|
|
119
|
-
// Multiplying the space available to the left of the text position by leftBoundFactor returns the max width of the text.
|
|
120
|
-
// Same for rightBoundFactor
|
|
121
|
-
let leftBoundFactor = 1;
|
|
122
|
-
let rightBoundFactor = 1;
|
|
123
|
-
if (tickLabelStyle?.textAnchor === 'start') {
|
|
124
|
-
leftBoundFactor = Infinity;
|
|
125
|
-
rightBoundFactor = 1;
|
|
126
|
-
} else if (tickLabelStyle?.textAnchor === 'end') {
|
|
127
|
-
leftBoundFactor = 1;
|
|
128
|
-
rightBoundFactor = Infinity;
|
|
129
|
-
} else {
|
|
130
|
-
leftBoundFactor = 2;
|
|
131
|
-
rightBoundFactor = 2;
|
|
132
|
-
}
|
|
133
|
-
if (angle > 90 && angle < 270) {
|
|
134
|
-
[leftBoundFactor, rightBoundFactor] = [rightBoundFactor, leftBoundFactor];
|
|
135
|
-
}
|
|
136
|
-
if (isRtl) {
|
|
137
|
-
[leftBoundFactor, rightBoundFactor] = [rightBoundFactor, leftBoundFactor];
|
|
138
|
-
}
|
|
139
|
-
for (const item of visibleLabels) {
|
|
140
|
-
if (item.formattedValue) {
|
|
141
|
-
// That maximum width of the tick depends on its proximity to the axis bounds.
|
|
142
|
-
const width = Math.min((item.offset + item.labelOffset) * leftBoundFactor, (drawingArea.left + drawingArea.width + drawingArea.right - item.offset - item.labelOffset) * rightBoundFactor);
|
|
143
|
-
const doesTextFit = text => doesTextFitInRect(text, {
|
|
144
|
-
width,
|
|
145
|
-
height: maxHeight,
|
|
146
|
-
angle,
|
|
147
|
-
measureText: string => getStringSize(string, tickLabelStyle)
|
|
148
|
-
});
|
|
149
|
-
shortenedLabels.set(item, ellipsize(item.formattedValue.toString(), doesTextFit));
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return shortenedLabels;
|
|
153
|
-
}
|
|
154
50
|
const XAxisRoot = styled(AxisRoot, {
|
|
155
51
|
name: 'MuiChartsXAxis',
|
|
156
52
|
slot: 'Root'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TickItemType } from "../hooks/useTicks.js";
|
|
2
|
+
import { ChartsXAxisProps, ComputedXAxis } from "../models/axis.js";
|
|
3
|
+
export declare function getVisibleLabels(xTicks: TickItemType[], {
|
|
4
|
+
tickLabelStyle: style,
|
|
5
|
+
tickLabelInterval,
|
|
6
|
+
tickLabelMinGap,
|
|
7
|
+
reverse,
|
|
8
|
+
isMounted,
|
|
9
|
+
isXInside
|
|
10
|
+
}: Pick<ChartsXAxisProps, 'tickLabelInterval' | 'tickLabelStyle'> & Pick<ComputedXAxis, 'reverse'> & {
|
|
11
|
+
isMounted: boolean;
|
|
12
|
+
tickLabelMinGap: NonNullable<ChartsXAxisProps['tickLabelMinGap']>;
|
|
13
|
+
isXInside: (x: number) => boolean;
|
|
14
|
+
}): Set<TickItemType>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { getMinXTranslation } from "../internals/geometry.js";
|
|
4
|
+
import { getWordsByLines } from "../internals/getWordsByLines.js";
|
|
5
|
+
|
|
6
|
+
/* Returns a set of indices of the tick labels that should be visible. */
|
|
7
|
+
export function getVisibleLabels(xTicks, {
|
|
8
|
+
tickLabelStyle: style,
|
|
9
|
+
tickLabelInterval,
|
|
10
|
+
tickLabelMinGap,
|
|
11
|
+
reverse,
|
|
12
|
+
isMounted,
|
|
13
|
+
isXInside
|
|
14
|
+
}) {
|
|
15
|
+
const getTickLabelSize = tick => {
|
|
16
|
+
if (!isMounted || tick.formattedValue === undefined) {
|
|
17
|
+
return {
|
|
18
|
+
width: 0,
|
|
19
|
+
height: 0
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const tickSizes = getWordsByLines({
|
|
23
|
+
style,
|
|
24
|
+
needsComputation: true,
|
|
25
|
+
text: tick.formattedValue
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
width: Math.max(...tickSizes.map(size => size.width)),
|
|
29
|
+
height: Math.max(tickSizes.length * tickSizes[0].height)
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
if (typeof tickLabelInterval === 'function') {
|
|
33
|
+
return new Set(xTicks.filter((item, index) => tickLabelInterval(item.value, index)));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Filter label to avoid overlap
|
|
37
|
+
let previousTextLimit = 0;
|
|
38
|
+
const direction = reverse ? -1 : 1;
|
|
39
|
+
return new Set(xTicks.filter((item, labelIndex) => {
|
|
40
|
+
const {
|
|
41
|
+
offset,
|
|
42
|
+
labelOffset
|
|
43
|
+
} = item;
|
|
44
|
+
const textPosition = offset + labelOffset;
|
|
45
|
+
if (labelIndex > 0 && direction * textPosition < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (!isXInside(textPosition)) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Measuring text width is expensive, so we need to delay it as much as possible to improve performance. */
|
|
53
|
+
const {
|
|
54
|
+
width,
|
|
55
|
+
height
|
|
56
|
+
} = getTickLabelSize(item);
|
|
57
|
+
const distance = getMinXTranslation(width, height, style?.angle);
|
|
58
|
+
const currentTextLimit = textPosition - direction * distance / 2;
|
|
59
|
+
if (labelIndex > 0 && direction * currentTextLimit < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
60
|
+
// Except for the first label, we skip all label that overlap with the last accepted.
|
|
61
|
+
// Notice that the early return prevents `previousTextLimit` from being updated.
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
previousTextLimit = textPosition + direction * distance / 2;
|
|
65
|
+
return true;
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TickItemType } from "../hooks/useTicks.js";
|
|
2
|
+
import { ChartsXAxisProps } from "../models/axis.js";
|
|
3
|
+
import { ChartDrawingArea } from "../hooks/useDrawingArea.js";
|
|
4
|
+
export declare function shortenLabels(visibleLabels: Set<TickItemType>, drawingArea: Pick<ChartDrawingArea, 'left' | 'width' | 'right'>, maxHeight: number, isRtl: boolean, tickLabelStyle: ChartsXAxisProps['tickLabelStyle']): Map<TickItemType, string>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { clampAngle } from "../internals/clampAngle.js";
|
|
2
|
+
import { doesTextFitInRect, ellipsize } from "../internals/ellipsize.js";
|
|
3
|
+
import { getStringSize } from "../internals/domUtils.js";
|
|
4
|
+
export function shortenLabels(visibleLabels, drawingArea, maxHeight, isRtl, tickLabelStyle) {
|
|
5
|
+
const shortenedLabels = new Map();
|
|
6
|
+
const angle = clampAngle(tickLabelStyle?.angle ?? 0);
|
|
7
|
+
|
|
8
|
+
// Multiplying the space available to the left of the text position by leftBoundFactor returns the max width of the text.
|
|
9
|
+
// Same for rightBoundFactor
|
|
10
|
+
let leftBoundFactor = 1;
|
|
11
|
+
let rightBoundFactor = 1;
|
|
12
|
+
if (tickLabelStyle?.textAnchor === 'start') {
|
|
13
|
+
leftBoundFactor = Infinity;
|
|
14
|
+
rightBoundFactor = 1;
|
|
15
|
+
} else if (tickLabelStyle?.textAnchor === 'end') {
|
|
16
|
+
leftBoundFactor = 1;
|
|
17
|
+
rightBoundFactor = Infinity;
|
|
18
|
+
} else {
|
|
19
|
+
leftBoundFactor = 2;
|
|
20
|
+
rightBoundFactor = 2;
|
|
21
|
+
}
|
|
22
|
+
if (angle > 90 && angle < 270) {
|
|
23
|
+
[leftBoundFactor, rightBoundFactor] = [rightBoundFactor, leftBoundFactor];
|
|
24
|
+
}
|
|
25
|
+
if (isRtl) {
|
|
26
|
+
[leftBoundFactor, rightBoundFactor] = [rightBoundFactor, leftBoundFactor];
|
|
27
|
+
}
|
|
28
|
+
for (const item of visibleLabels) {
|
|
29
|
+
if (item.formattedValue) {
|
|
30
|
+
// That maximum width of the tick depends on its proximity to the axis bounds.
|
|
31
|
+
const width = Math.min((item.offset + item.labelOffset) * leftBoundFactor, (drawingArea.left + drawingArea.width + drawingArea.right - item.offset - item.labelOffset) * rightBoundFactor);
|
|
32
|
+
const doesTextFit = text => doesTextFitInRect(text, {
|
|
33
|
+
width,
|
|
34
|
+
height: maxHeight,
|
|
35
|
+
angle,
|
|
36
|
+
measureText: string => getStringSize(string, tickLabelStyle)
|
|
37
|
+
});
|
|
38
|
+
shortenedLabels.set(item, ellipsize(item.formattedValue.toString(), doesTextFit));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return shortenedLabels;
|
|
42
|
+
}
|
|
@@ -11,7 +11,6 @@ import { useThemeProps, styled, useTheme } from '@mui/material/styles';
|
|
|
11
11
|
import { useRtl } from '@mui/system/RtlProvider';
|
|
12
12
|
import { useIsHydrated } from "../hooks/useIsHydrated.js";
|
|
13
13
|
import { getDefaultBaseline, getDefaultTextAnchor } from "../ChartsText/defaultTextPlacement.js";
|
|
14
|
-
import { doesTextFitInRect, ellipsize } from "../internals/ellipsize.js";
|
|
15
14
|
import { getStringSize } from "../internals/domUtils.js";
|
|
16
15
|
import { useTicks } from "../hooks/useTicks.js";
|
|
17
16
|
import { useDrawingArea } from "../hooks/useDrawingArea.js";
|
|
@@ -22,8 +21,8 @@ import { isInfinity } from "../internals/isInfinity.js";
|
|
|
22
21
|
import { isBandScale } from "../internals/isBandScale.js";
|
|
23
22
|
import { useChartContext } from "../context/ChartProvider/index.js";
|
|
24
23
|
import { useYAxes } from "../hooks/index.js";
|
|
25
|
-
import { clampAngle } from "../internals/clampAngle.js";
|
|
26
24
|
import { invertTextAnchor } from "../internals/invertTextAnchor.js";
|
|
25
|
+
import { shortenLabels } from "./shortenLabels.js";
|
|
27
26
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
28
27
|
const useUtilityClasses = ownerState => {
|
|
29
28
|
const {
|
|
@@ -46,42 +45,6 @@ const useUtilityClasses = ownerState => {
|
|
|
46
45
|
const TICK_LABEL_GAP = 2;
|
|
47
46
|
/* Gap between the axis label and tick labels. */
|
|
48
47
|
const AXIS_LABEL_TICK_LABEL_GAP = 2;
|
|
49
|
-
function shortenLabels(visibleLabels, drawingArea, maxWidth, isRtl, tickLabelStyle) {
|
|
50
|
-
const shortenedLabels = new Map();
|
|
51
|
-
const angle = clampAngle(tickLabelStyle?.angle ?? 0);
|
|
52
|
-
let topBoundFactor = 1;
|
|
53
|
-
let bottomBoundFactor = 1;
|
|
54
|
-
if (tickLabelStyle?.textAnchor === 'start') {
|
|
55
|
-
topBoundFactor = Infinity;
|
|
56
|
-
bottomBoundFactor = 1;
|
|
57
|
-
} else if (tickLabelStyle?.textAnchor === 'end') {
|
|
58
|
-
topBoundFactor = 1;
|
|
59
|
-
bottomBoundFactor = Infinity;
|
|
60
|
-
} else {
|
|
61
|
-
topBoundFactor = 2;
|
|
62
|
-
bottomBoundFactor = 2;
|
|
63
|
-
}
|
|
64
|
-
if (angle > 180) {
|
|
65
|
-
[topBoundFactor, bottomBoundFactor] = [bottomBoundFactor, topBoundFactor];
|
|
66
|
-
}
|
|
67
|
-
if (isRtl) {
|
|
68
|
-
[topBoundFactor, bottomBoundFactor] = [bottomBoundFactor, topBoundFactor];
|
|
69
|
-
}
|
|
70
|
-
for (const item of visibleLabels) {
|
|
71
|
-
if (item.formattedValue) {
|
|
72
|
-
// That maximum height of the tick depends on its proximity to the axis bounds.
|
|
73
|
-
const height = Math.min((item.offset + item.labelOffset) * topBoundFactor, (drawingArea.top + drawingArea.height + drawingArea.bottom - item.offset - item.labelOffset) * bottomBoundFactor);
|
|
74
|
-
const doesTextFit = text => doesTextFitInRect(text, {
|
|
75
|
-
width: maxWidth,
|
|
76
|
-
height,
|
|
77
|
-
angle,
|
|
78
|
-
measureText: string => getStringSize(string, tickLabelStyle)
|
|
79
|
-
});
|
|
80
|
-
shortenedLabels.set(item, ellipsize(item.formattedValue.toString(), doesTextFit));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return shortenedLabels;
|
|
84
|
-
}
|
|
85
48
|
const YAxisRoot = styled(AxisRoot, {
|
|
86
49
|
name: 'MuiChartsYAxis',
|
|
87
50
|
slot: 'Root'
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ChartDrawingArea } from "../hooks/index.js";
|
|
2
|
+
import { TickItemType } from "../hooks/useTicks.js";
|
|
3
|
+
import { ChartsYAxisProps } from "../models/index.js";
|
|
4
|
+
export declare function shortenLabels(visibleLabels: TickItemType[], drawingArea: Pick<ChartDrawingArea, 'top' | 'height' | 'bottom'>, maxWidth: number, isRtl: boolean, tickLabelStyle: ChartsYAxisProps['tickLabelStyle']): Map<TickItemType, string>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { clampAngle } from "../internals/clampAngle.js";
|
|
4
|
+
import { doesTextFitInRect, ellipsize } from "../internals/ellipsize.js";
|
|
5
|
+
import { getStringSize } from "../internals/domUtils.js";
|
|
6
|
+
export function shortenLabels(visibleLabels, drawingArea, maxWidth, isRtl, tickLabelStyle) {
|
|
7
|
+
const shortenedLabels = new Map();
|
|
8
|
+
const angle = clampAngle(tickLabelStyle?.angle ?? 0);
|
|
9
|
+
let topBoundFactor = 1;
|
|
10
|
+
let bottomBoundFactor = 1;
|
|
11
|
+
if (tickLabelStyle?.textAnchor === 'start') {
|
|
12
|
+
topBoundFactor = Infinity;
|
|
13
|
+
bottomBoundFactor = 1;
|
|
14
|
+
} else if (tickLabelStyle?.textAnchor === 'end') {
|
|
15
|
+
topBoundFactor = 1;
|
|
16
|
+
bottomBoundFactor = Infinity;
|
|
17
|
+
} else {
|
|
18
|
+
topBoundFactor = 2;
|
|
19
|
+
bottomBoundFactor = 2;
|
|
20
|
+
}
|
|
21
|
+
if (angle > 180) {
|
|
22
|
+
[topBoundFactor, bottomBoundFactor] = [bottomBoundFactor, topBoundFactor];
|
|
23
|
+
}
|
|
24
|
+
if (isRtl) {
|
|
25
|
+
[topBoundFactor, bottomBoundFactor] = [bottomBoundFactor, topBoundFactor];
|
|
26
|
+
}
|
|
27
|
+
for (const item of visibleLabels) {
|
|
28
|
+
if (item.formattedValue) {
|
|
29
|
+
// That maximum height of the tick depends on its proximity to the axis bounds.
|
|
30
|
+
const height = Math.min((item.offset + item.labelOffset) * topBoundFactor, (drawingArea.top + drawingArea.height + drawingArea.bottom - item.offset - item.labelOffset) * bottomBoundFactor);
|
|
31
|
+
const doesTextFit = text => doesTextFitInRect(text, {
|
|
32
|
+
width: maxWidth,
|
|
33
|
+
height,
|
|
34
|
+
angle,
|
|
35
|
+
measureText: string => getStringSize(string, tickLabelStyle)
|
|
36
|
+
});
|
|
37
|
+
shortenedLabels.set(item, ellipsize(item.formattedValue.toString(), doesTextFit));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return shortenedLabels;
|
|
41
|
+
}
|
|
@@ -34,7 +34,10 @@ function AnimatedArea(props) {
|
|
|
34
34
|
// eslint-disable-next-line no-nested-ternary
|
|
35
35
|
ownerState.isHighlighted ? 'brightness(140%)' : ownerState.gradientId ? undefined : 'brightness(120%)',
|
|
36
36
|
opacity: ownerState.isFaded ? 0.3 : 1,
|
|
37
|
-
stroke: "none"
|
|
37
|
+
stroke: "none",
|
|
38
|
+
"data-series": ownerState.id,
|
|
39
|
+
"data-highlighted": ownerState.isHighlighted || undefined,
|
|
40
|
+
"data-faded": ownerState.isFaded || undefined
|
|
38
41
|
}, other, animatedProps))
|
|
39
42
|
});
|
|
40
43
|
}
|
|
@@ -36,7 +36,10 @@ const AnimatedLine = /*#__PURE__*/React.forwardRef(function AnimatedLine(props,
|
|
|
36
36
|
strokeLinejoin: "round",
|
|
37
37
|
fill: "none",
|
|
38
38
|
filter: ownerState.isHighlighted ? 'brightness(120%)' : undefined,
|
|
39
|
-
opacity: ownerState.isFaded ? 0.3 : 1
|
|
39
|
+
opacity: ownerState.isFaded ? 0.3 : 1,
|
|
40
|
+
"data-series": ownerState.id,
|
|
41
|
+
"data-highlighted": ownerState.isHighlighted || undefined,
|
|
42
|
+
"data-faded": ownerState.isFaded || undefined
|
|
40
43
|
}, other, animateProps))
|
|
41
44
|
});
|
|
42
45
|
});
|
|
@@ -69,7 +69,10 @@ function CircleMarkElement(props) {
|
|
|
69
69
|
className: classes.root,
|
|
70
70
|
onClick: onClick,
|
|
71
71
|
cursor: onClick ? 'pointer' : 'unset'
|
|
72
|
-
}, interactionProps
|
|
72
|
+
}, interactionProps, {
|
|
73
|
+
"data-highlighted": isHighlighted || undefined,
|
|
74
|
+
"data-faded": isFaded || undefined
|
|
75
|
+
}));
|
|
73
76
|
}
|
|
74
77
|
process.env.NODE_ENV !== "production" ? CircleMarkElement.propTypes = {
|
|
75
78
|
// ----------------------------- Warning --------------------------------
|
|
@@ -77,7 +77,10 @@ function MarkElement(props) {
|
|
|
77
77
|
d: d3Symbol(d3SymbolsFill[getSymbol(shape)])(),
|
|
78
78
|
onClick: onClick,
|
|
79
79
|
cursor: onClick ? 'pointer' : 'unset'
|
|
80
|
-
}, interactionProps
|
|
80
|
+
}, interactionProps, {
|
|
81
|
+
"data-highlighted": isHighlighted || undefined,
|
|
82
|
+
"data-faded": isFaded || undefined
|
|
83
|
+
}));
|
|
81
84
|
}
|
|
82
85
|
process.env.NODE_ENV !== "production" ? MarkElement.propTypes = {
|
|
83
86
|
// ----------------------------- Warning --------------------------------
|
|
@@ -102,6 +102,7 @@ function MarkPlot(props) {
|
|
|
102
102
|
});
|
|
103
103
|
return /*#__PURE__*/_jsx("g", {
|
|
104
104
|
clipPath: `url(#${clipId})`,
|
|
105
|
+
"data-series": seriesId,
|
|
105
106
|
children: xData?.map((x, index) => {
|
|
106
107
|
const value = data[index] == null ? null : stackedData[index][1];
|
|
107
108
|
return {
|
package/esm/PieChart/PieArc.js
CHANGED
|
@@ -94,7 +94,9 @@ const PieArc = /*#__PURE__*/React.forwardRef(function PieArc(props, ref) {
|
|
|
94
94
|
opacity: ownerState.isFaded ? 0.3 : 1,
|
|
95
95
|
filter: ownerState.isHighlighted ? 'brightness(120%)' : 'none',
|
|
96
96
|
strokeWidth: 1,
|
|
97
|
-
strokeLinejoin: "round"
|
|
97
|
+
strokeLinejoin: "round",
|
|
98
|
+
"data-highlighted": ownerState.isHighlighted || undefined,
|
|
99
|
+
"data-faded": ownerState.isFaded || undefined
|
|
98
100
|
}, other, interactionProps, animatedProps));
|
|
99
101
|
});
|
|
100
102
|
if (process.env.NODE_ENV !== "production") PieArc.displayName = "PieArc";
|