@mui/x-charts 8.14.1 → 8.15.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/BarChart.js +8 -0
- package/BarChart/BarChart.plugins.d.ts +2 -1
- package/BarChart/BarChart.plugins.js +2 -1
- package/BarChart/useBarChartProps.js +4 -2
- package/CHANGELOG.md +107 -0
- package/ChartContainer/ChartContainer.js +8 -0
- package/ChartContainer/useChartContainerProps.js +4 -2
- package/ChartsBrushOverlay/ChartsBrushOverlay.classes.d.ts +12 -0
- package/ChartsBrushOverlay/ChartsBrushOverlay.classes.js +9 -0
- package/ChartsBrushOverlay/ChartsBrushOverlay.d.ts +6 -0
- package/ChartsBrushOverlay/ChartsBrushOverlay.js +102 -0
- package/ChartsBrushOverlay/index.d.ts +4 -0
- package/ChartsBrushOverlay/index.js +19 -0
- package/ChartsReferenceLine/ChartsReferenceLine.js +1 -1
- package/ChartsReferenceLine/ChartsXReferenceLine.js +13 -8
- package/ChartsReferenceLine/ChartsYReferenceLine.js +13 -8
- package/ChartsReferenceLine/common.d.ts +3 -1
- package/ChartsReferenceLine/common.js +3 -1
- package/ChartsTooltip/ChartsTooltipContainer.js +20 -2
- package/ChartsXAxis/getVisibleLabels.js +45 -25
- package/LineChart/LineChart.js +8 -0
- package/LineChart/LineChart.plugins.d.ts +2 -1
- package/LineChart/LineChart.plugins.js +2 -1
- package/LineChart/useLineChartProps.js +4 -2
- package/ScatterChart/ScatterChart.js +8 -0
- package/ScatterChart/ScatterChart.plugins.d.ts +2 -1
- package/ScatterChart/ScatterChart.plugins.js +2 -1
- package/ScatterChart/useScatterChartProps.js +5 -3
- package/SparkLineChart/SparkLineChart.js +8 -0
- package/esm/BarChart/BarChart.js +8 -0
- package/esm/BarChart/BarChart.plugins.d.ts +2 -1
- package/esm/BarChart/BarChart.plugins.js +2 -1
- package/esm/BarChart/useBarChartProps.js +4 -2
- package/esm/ChartContainer/ChartContainer.js +8 -0
- package/esm/ChartContainer/useChartContainerProps.js +4 -2
- package/esm/ChartsBrushOverlay/ChartsBrushOverlay.classes.d.ts +12 -0
- package/esm/ChartsBrushOverlay/ChartsBrushOverlay.classes.js +2 -0
- package/esm/ChartsBrushOverlay/ChartsBrushOverlay.d.ts +6 -0
- package/esm/ChartsBrushOverlay/ChartsBrushOverlay.js +95 -0
- package/esm/ChartsBrushOverlay/index.d.ts +4 -0
- package/esm/ChartsBrushOverlay/index.js +2 -0
- package/esm/ChartsReferenceLine/ChartsReferenceLine.js +1 -1
- package/esm/ChartsReferenceLine/ChartsXReferenceLine.js +14 -9
- package/esm/ChartsReferenceLine/ChartsYReferenceLine.js +14 -9
- package/esm/ChartsReferenceLine/common.d.ts +3 -1
- package/esm/ChartsReferenceLine/common.js +2 -0
- package/esm/ChartsTooltip/ChartsTooltipContainer.js +20 -2
- package/esm/ChartsXAxis/getVisibleLabels.js +45 -25
- package/esm/LineChart/LineChart.js +8 -0
- package/esm/LineChart/LineChart.plugins.d.ts +2 -1
- package/esm/LineChart/LineChart.plugins.js +2 -1
- package/esm/LineChart/useLineChartProps.js +4 -2
- package/esm/ScatterChart/ScatterChart.js +8 -0
- package/esm/ScatterChart/ScatterChart.plugins.d.ts +2 -1
- package/esm/ScatterChart/ScatterChart.plugins.js +2 -1
- package/esm/ScatterChart/useScatterChartProps.js +5 -3
- package/esm/SparkLineChart/SparkLineChart.js +8 -0
- package/esm/hooks/index.d.ts +2 -1
- package/esm/hooks/index.js +2 -1
- package/esm/hooks/useBrush.d.ts +18 -0
- package/esm/hooks/useBrush.js +16 -0
- package/esm/index.d.ts +2 -1
- package/esm/index.js +2 -1
- package/esm/internals/domUtils.d.ts +9 -4
- package/esm/internals/domUtils.js +115 -52
- package/esm/internals/index.d.ts +1 -0
- package/esm/internals/index.js +1 -0
- package/esm/internals/plugins/allPlugins.d.ts +4 -3
- package/esm/internals/plugins/allPlugins.js +2 -1
- package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +16 -10
- package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +2 -2
- package/esm/internals/plugins/featurePlugins/useChartBrush/index.d.ts +3 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/index.js +3 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.d.ts +3 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.js +109 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.d.ts +82 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.js +75 -0
- package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.types.d.ts +72 -0
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/createZoomLookup.js +3 -2
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.js +2 -2
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.d.ts +2 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.js +8 -3
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts +3 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.d.ts +4 -4
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +13 -6
- package/esm/internals/plugins/utils/selectors.d.ts +1 -1
- package/esm/locales/elGR.js +97 -99
- package/esm/tests/constants.js +1 -0
- package/hooks/index.d.ts +2 -1
- package/hooks/index.js +12 -0
- package/hooks/useBrush.d.ts +18 -0
- package/hooks/useBrush.js +21 -0
- package/index.d.ts +2 -1
- package/index.js +13 -1
- package/internals/domUtils.d.ts +9 -4
- package/internals/domUtils.js +119 -54
- package/internals/index.d.ts +1 -0
- package/internals/index.js +12 -0
- package/internals/plugins/allPlugins.d.ts +4 -3
- package/internals/plugins/allPlugins.js +2 -1
- package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +16 -10
- package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +2 -2
- package/internals/plugins/featurePlugins/useChartBrush/index.d.ts +3 -0
- package/internals/plugins/featurePlugins/useChartBrush/index.js +38 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.d.ts +3 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.js +117 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.d.ts +82 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.js +82 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.types.d.ts +72 -0
- package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.types.js +5 -0
- package/internals/plugins/featurePlugins/useChartCartesianAxis/createZoomLookup.js +3 -2
- package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.js +2 -2
- package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.d.ts +2 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.js +8 -3
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts +3 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.d.ts +4 -4
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +13 -6
- package/internals/plugins/utils/selectors.d.ts +1 -1
- package/locales/elGR.js +97 -99
- package/package.json +3 -3
- package/tests/constants.js +7 -0
- package/esm/internals/Flatbush.bench.js +0 -42
- package/internals/Flatbush.bench.d.ts +0 -1
- package/internals/Flatbush.bench.js +0 -44
- /package/esm/internals/{Flatbush.bench.d.ts → plugins/featurePlugins/useChartBrush/useChartBrush.types.js} +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ChartsReferenceLineClasses } from "./chartsReferenceLineClasses.js";
|
|
2
2
|
import { ChartsTextStyle } from "../ChartsText/index.js";
|
|
3
3
|
import { AxisId } from "../models/axis.js";
|
|
4
|
+
export declare const DEFAULT_SPACING = 5;
|
|
5
|
+
export declare const DEFAULT_SPACING_MIDDLE_OTHER_AXIS = 0;
|
|
4
6
|
export type CommonChartsReferenceLineProps = {
|
|
5
7
|
/**
|
|
6
8
|
* The alignment if the label is in the chart drawing area.
|
|
@@ -14,7 +16,7 @@ export type CommonChartsReferenceLineProps = {
|
|
|
14
16
|
/**
|
|
15
17
|
* Additional space around the label in px.
|
|
16
18
|
* Can be a number or an object `{ x, y }` to distinguish space with the reference line and space with axes.
|
|
17
|
-
* @default 5
|
|
19
|
+
* @default { x: 0, y: 5 } on a horizontal line and { x: 5, y: 0 } on a vertical line.
|
|
18
20
|
*/
|
|
19
21
|
spacing?: number | {
|
|
20
22
|
x?: number;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import { styled } from '@mui/material/styles';
|
|
3
3
|
import { referenceLineClasses } from "./chartsReferenceLineClasses.js";
|
|
4
|
+
export const DEFAULT_SPACING = 5;
|
|
5
|
+
export const DEFAULT_SPACING_MIDDLE_OTHER_AXIS = 0;
|
|
4
6
|
export const ReferenceLineRoot = styled('g')(({
|
|
5
7
|
theme
|
|
6
8
|
}) => ({
|
|
@@ -20,8 +20,10 @@ import { selectorChartsInteractionAxisTooltip } from "../internals/plugins/featu
|
|
|
20
20
|
import { selectorChartsInteractionPolarAxisTooltip } from "../internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarInteraction.selectors.js";
|
|
21
21
|
import { useAxisSystem } from "../hooks/useAxisSystem.js";
|
|
22
22
|
import { useSvgRef } from "../hooks/index.js";
|
|
23
|
+
import { selectorBrushShouldPreventTooltip } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
24
|
+
import { createSelector } from "../internals/plugins/utils/selectors.js";
|
|
23
25
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
24
|
-
const
|
|
26
|
+
const selectorReturnFalse = () => false;
|
|
25
27
|
const ChartsTooltipRoot = styled(Popper, {
|
|
26
28
|
name: 'MuiChartsTooltip',
|
|
27
29
|
slot: 'Root'
|
|
@@ -31,6 +33,21 @@ const ChartsTooltipRoot = styled(Popper, {
|
|
|
31
33
|
pointerEvents: 'none',
|
|
32
34
|
zIndex: theme.zIndex.modal
|
|
33
35
|
}));
|
|
36
|
+
const selectorSelectIsOpenSelector = createSelector([selectorBrushShouldPreventTooltip, (_, trigger) => trigger, (_, __, axisSystem) => axisSystem], (shouldPreventBecauseOfBrush, trigger, axisSystem) => {
|
|
37
|
+
if (shouldPreventBecauseOfBrush) {
|
|
38
|
+
return selectorReturnFalse;
|
|
39
|
+
}
|
|
40
|
+
if (trigger === 'item') {
|
|
41
|
+
return selectorChartsInteractionItemIsDefined;
|
|
42
|
+
}
|
|
43
|
+
if (axisSystem === 'polar') {
|
|
44
|
+
return selectorChartsInteractionPolarAxisTooltip;
|
|
45
|
+
}
|
|
46
|
+
if (axisSystem === 'cartesian') {
|
|
47
|
+
return selectorChartsInteractionAxisTooltip;
|
|
48
|
+
}
|
|
49
|
+
return selectorReturnFalse;
|
|
50
|
+
});
|
|
34
51
|
|
|
35
52
|
/**
|
|
36
53
|
* Demos:
|
|
@@ -63,7 +80,8 @@ function ChartsTooltipContainer(inProps) {
|
|
|
63
80
|
}));
|
|
64
81
|
const axisSystem = useAxisSystem();
|
|
65
82
|
const store = useStore();
|
|
66
|
-
const
|
|
83
|
+
const isOpenSelector = useSelector(store, selectorSelectIsOpenSelector, [trigger, axisSystem]);
|
|
84
|
+
const isOpen = useSelector(store, isOpenSelector);
|
|
67
85
|
React.useEffect(() => {
|
|
68
86
|
const element = svgRef.current;
|
|
69
87
|
if (element === null) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { getMinXTranslation } from "../internals/geometry.js";
|
|
4
|
-
import {
|
|
4
|
+
import { batchMeasureStrings } from "../internals/domUtils.js";
|
|
5
5
|
|
|
6
6
|
/* Returns a set of indices of the tick labels that should be visible. */
|
|
7
7
|
export function getVisibleLabels(xTicks, {
|
|
@@ -12,23 +12,6 @@ export function getVisibleLabels(xTicks, {
|
|
|
12
12
|
isMounted,
|
|
13
13
|
isXInside
|
|
14
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
15
|
if (typeof tickLabelInterval === 'function') {
|
|
33
16
|
return new Set(xTicks.filter((item, index) => tickLabelInterval(item.value, index)));
|
|
34
17
|
}
|
|
@@ -36,7 +19,7 @@ export function getVisibleLabels(xTicks, {
|
|
|
36
19
|
// Filter label to avoid overlap
|
|
37
20
|
let previousTextLimit = 0;
|
|
38
21
|
const direction = reverse ? -1 : 1;
|
|
39
|
-
|
|
22
|
+
const candidateTickLabels = xTicks.filter(item => {
|
|
40
23
|
const {
|
|
41
24
|
offset,
|
|
42
25
|
labelOffset,
|
|
@@ -46,18 +29,25 @@ export function getVisibleLabels(xTicks, {
|
|
|
46
29
|
return false;
|
|
47
30
|
}
|
|
48
31
|
const textPosition = offset + labelOffset;
|
|
32
|
+
return isXInside(textPosition);
|
|
33
|
+
});
|
|
34
|
+
const sizeMap = measureTickLabels(candidateTickLabels, style);
|
|
35
|
+
return new Set(candidateTickLabels.filter((item, labelIndex) => {
|
|
36
|
+
const {
|
|
37
|
+
offset,
|
|
38
|
+
labelOffset
|
|
39
|
+
} = item;
|
|
40
|
+
const textPosition = offset + labelOffset;
|
|
49
41
|
if (labelIndex > 0 && direction * textPosition < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
50
42
|
return false;
|
|
51
43
|
}
|
|
52
|
-
if (!isXInside(textPosition)) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* Measuring text width is expensive, so we need to delay it as much as possible to improve performance. */
|
|
57
44
|
const {
|
|
58
45
|
width,
|
|
59
46
|
height
|
|
60
|
-
} = getTickLabelSize(item)
|
|
47
|
+
} = isMounted ? getTickLabelSize(sizeMap, item) : {
|
|
48
|
+
width: 0,
|
|
49
|
+
height: 0
|
|
50
|
+
};
|
|
61
51
|
const distance = getMinXTranslation(width, height, style?.angle);
|
|
62
52
|
const currentTextLimit = textPosition - direction * distance / 2;
|
|
63
53
|
if (labelIndex > 0 && direction * currentTextLimit < direction * (previousTextLimit + tickLabelMinGap)) {
|
|
@@ -68,4 +58,34 @@ export function getVisibleLabels(xTicks, {
|
|
|
68
58
|
previousTextLimit = textPosition + direction * distance / 2;
|
|
69
59
|
return true;
|
|
70
60
|
}));
|
|
61
|
+
}
|
|
62
|
+
function getTickLabelSize(sizeMap, tick) {
|
|
63
|
+
if (tick.formattedValue === undefined) {
|
|
64
|
+
return {
|
|
65
|
+
width: 0,
|
|
66
|
+
height: 0
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
let width = 0;
|
|
70
|
+
let height = 0;
|
|
71
|
+
for (const line of tick.formattedValue.split('\n')) {
|
|
72
|
+
const lineSize = sizeMap.get(line);
|
|
73
|
+
if (lineSize) {
|
|
74
|
+
width = Math.max(width, lineSize.width);
|
|
75
|
+
height += lineSize.height;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
width,
|
|
80
|
+
height
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function measureTickLabels(ticks, style) {
|
|
84
|
+
const strings = new Set();
|
|
85
|
+
for (const tick of ticks) {
|
|
86
|
+
if (tick.formattedValue) {
|
|
87
|
+
tick.formattedValue.split('\n').forEach(line => strings.add(line));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return batchMeasureStrings(strings, style);
|
|
71
91
|
}
|
|
@@ -90,6 +90,14 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
|
|
|
90
90
|
x: PropTypes.oneOf(['band', 'line', 'none']),
|
|
91
91
|
y: PropTypes.oneOf(['band', 'line', 'none'])
|
|
92
92
|
}),
|
|
93
|
+
/**
|
|
94
|
+
* Configuration for the brush interaction.
|
|
95
|
+
*/
|
|
96
|
+
brushConfig: PropTypes.shape({
|
|
97
|
+
enabled: PropTypes.bool,
|
|
98
|
+
preventHighlight: PropTypes.bool,
|
|
99
|
+
preventTooltip: PropTypes.bool
|
|
100
|
+
}),
|
|
93
101
|
children: PropTypes.node,
|
|
94
102
|
className: PropTypes.string,
|
|
95
103
|
/**
|
|
@@ -4,5 +4,6 @@ import { UseChartInteractionSignature } from "../internals/plugins/featurePlugin
|
|
|
4
4
|
import { UseChartHighlightSignature } from "../internals/plugins/featurePlugins/useChartHighlight/index.js";
|
|
5
5
|
import { UseChartKeyboardNavigationSignature } from "../internals/plugins/featurePlugins/useChartKeyboardNavigation/index.js";
|
|
6
6
|
import { ConvertSignaturesIntoPlugins } from "../internals/plugins/models/helpers.js";
|
|
7
|
-
|
|
7
|
+
import { UseChartBrushSignature } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
8
|
+
export type LineChartPluginSignatures = [UseChartZAxisSignature, UseChartBrushSignature, UseChartCartesianAxisSignature<'line'>, UseChartInteractionSignature, UseChartHighlightSignature, UseChartKeyboardNavigationSignature];
|
|
8
9
|
export declare const LINE_CHART_PLUGINS: ConvertSignaturesIntoPlugins<LineChartPluginSignatures>;
|
|
@@ -3,4 +3,5 @@ import { useChartCartesianAxis } from "../internals/plugins/featurePlugins/useCh
|
|
|
3
3
|
import { useChartInteraction } from "../internals/plugins/featurePlugins/useChartInteraction/index.js";
|
|
4
4
|
import { useChartHighlight } from "../internals/plugins/featurePlugins/useChartHighlight/index.js";
|
|
5
5
|
import { useChartKeyboardNavigation } from "../internals/plugins/featurePlugins/useChartKeyboardNavigation/index.js";
|
|
6
|
-
|
|
6
|
+
import { useChartBrush } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
7
|
+
export const LINE_CHART_PLUGINS = [useChartZAxis, useChartBrush, useChartCartesianAxis, useChartInteraction, useChartHighlight, useChartKeyboardNavigation];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
4
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
5
|
-
const _excluded = ["xAxis", "yAxis", "series", "width", "height", "margin", "colors", "dataset", "sx", "onAreaClick", "onLineClick", "onMarkClick", "axisHighlight", "disableLineItemHighlight", "hideLegend", "grid", "children", "slots", "slotProps", "skipAnimation", "loading", "highlightedItem", "onHighlightChange", "className", "showToolbar"];
|
|
5
|
+
const _excluded = ["xAxis", "yAxis", "series", "width", "height", "margin", "colors", "dataset", "sx", "onAreaClick", "onLineClick", "onMarkClick", "axisHighlight", "disableLineItemHighlight", "hideLegend", "grid", "children", "slots", "slotProps", "skipAnimation", "loading", "highlightedItem", "onHighlightChange", "className", "showToolbar", "brushConfig"];
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import useId from '@mui/utils/useId';
|
|
8
8
|
import { DEFAULT_X_AXIS_KEY } from "../constants/index.js";
|
|
@@ -39,7 +39,8 @@ export const useLineChartProps = props => {
|
|
|
39
39
|
loading,
|
|
40
40
|
highlightedItem,
|
|
41
41
|
onHighlightChange,
|
|
42
|
-
className
|
|
42
|
+
className,
|
|
43
|
+
brushConfig
|
|
43
44
|
} = props,
|
|
44
45
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
45
46
|
const id = useId();
|
|
@@ -68,6 +69,7 @@ export const useLineChartProps = props => {
|
|
|
68
69
|
disableAxisListener: slotProps?.tooltip?.trigger !== 'axis' && axisHighlight?.x === 'none' && axisHighlight?.y === 'none',
|
|
69
70
|
className,
|
|
70
71
|
skipAnimation,
|
|
72
|
+
brushConfig,
|
|
71
73
|
plugins: LINE_CHART_PLUGINS
|
|
72
74
|
});
|
|
73
75
|
const gridProps = {
|
|
@@ -80,6 +80,14 @@ process.env.NODE_ENV !== "production" ? ScatterChart.propTypes = {
|
|
|
80
80
|
x: PropTypes.oneOf(['band', 'line', 'none']),
|
|
81
81
|
y: PropTypes.oneOf(['band', 'line', 'none'])
|
|
82
82
|
}),
|
|
83
|
+
/**
|
|
84
|
+
* Configuration for the brush interaction.
|
|
85
|
+
*/
|
|
86
|
+
brushConfig: PropTypes.shape({
|
|
87
|
+
enabled: PropTypes.bool,
|
|
88
|
+
preventHighlight: PropTypes.bool,
|
|
89
|
+
preventTooltip: PropTypes.bool
|
|
90
|
+
}),
|
|
83
91
|
children: PropTypes.node,
|
|
84
92
|
className: PropTypes.string,
|
|
85
93
|
/**
|
|
@@ -5,5 +5,6 @@ import { UseChartHighlightSignature } from "../internals/plugins/featurePlugins/
|
|
|
5
5
|
import { ConvertSignaturesIntoPlugins } from "../internals/plugins/models/helpers.js";
|
|
6
6
|
import { UseChartClosestPointSignature } from "../internals/plugins/featurePlugins/useChartClosestPoint/index.js";
|
|
7
7
|
import { UseChartKeyboardNavigationSignature } from "../internals/plugins/featurePlugins/useChartKeyboardNavigation/index.js";
|
|
8
|
-
|
|
8
|
+
import { UseChartBrushSignature } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
9
|
+
export type ScatterChartPluginSignatures = [UseChartZAxisSignature, UseChartBrushSignature, UseChartCartesianAxisSignature<'scatter'>, UseChartInteractionSignature, UseChartHighlightSignature, UseChartClosestPointSignature, UseChartKeyboardNavigationSignature];
|
|
9
10
|
export declare const SCATTER_CHART_PLUGINS: ConvertSignaturesIntoPlugins<ScatterChartPluginSignatures>;
|
|
@@ -4,4 +4,5 @@ import { useChartInteraction } from "../internals/plugins/featurePlugins/useChar
|
|
|
4
4
|
import { useChartHighlight } from "../internals/plugins/featurePlugins/useChartHighlight/index.js";
|
|
5
5
|
import { useChartClosestPoint } from "../internals/plugins/featurePlugins/useChartClosestPoint/index.js";
|
|
6
6
|
import { useChartKeyboardNavigation } from "../internals/plugins/featurePlugins/useChartKeyboardNavigation/index.js";
|
|
7
|
-
|
|
7
|
+
import { useChartBrush } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
8
|
+
export const SCATTER_CHART_PLUGINS = [useChartZAxis, useChartBrush, useChartCartesianAxis, useChartInteraction, useChartHighlight, useChartClosestPoint, useChartKeyboardNavigation];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
4
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
5
|
-
const _excluded = ["xAxis", "yAxis", "zAxis", "series", "axisHighlight", "voronoiMaxRadius", "disableVoronoi", "hideLegend", "width", "height", "margin", "colors", "sx", "grid", "onItemClick", "children", "slots", "slotProps", "loading", "highlightedItem", "onHighlightChange", "className", "showToolbar", "renderer"];
|
|
5
|
+
const _excluded = ["xAxis", "yAxis", "zAxis", "series", "axisHighlight", "voronoiMaxRadius", "disableVoronoi", "hideLegend", "width", "height", "margin", "colors", "sx", "grid", "onItemClick", "children", "slots", "slotProps", "loading", "highlightedItem", "onHighlightChange", "className", "showToolbar", "renderer", "brushConfig"];
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import { SCATTER_CHART_PLUGINS } from "./ScatterChart.plugins.js";
|
|
8
8
|
/**
|
|
@@ -35,7 +35,8 @@ export const useScatterChartProps = props => {
|
|
|
35
35
|
highlightedItem,
|
|
36
36
|
onHighlightChange,
|
|
37
37
|
className,
|
|
38
|
-
renderer
|
|
38
|
+
renderer,
|
|
39
|
+
brushConfig
|
|
39
40
|
} = props,
|
|
40
41
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
41
42
|
const seriesWithDefault = React.useMemo(() => series.map(s => _extends({
|
|
@@ -59,7 +60,8 @@ export const useScatterChartProps = props => {
|
|
|
59
60
|
className,
|
|
60
61
|
plugins: SCATTER_CHART_PLUGINS,
|
|
61
62
|
slots,
|
|
62
|
-
slotProps
|
|
63
|
+
slotProps,
|
|
64
|
+
brushConfig
|
|
63
65
|
});
|
|
64
66
|
const chartsAxisProps = {
|
|
65
67
|
slots,
|
|
@@ -179,6 +179,14 @@ process.env.NODE_ENV !== "production" ? SparkLineChart.propTypes = {
|
|
|
179
179
|
* @default 0
|
|
180
180
|
*/
|
|
181
181
|
baseline: PropTypes.oneOfType([PropTypes.oneOf(['max', 'min']), PropTypes.number]),
|
|
182
|
+
/**
|
|
183
|
+
* Configuration for the brush interaction.
|
|
184
|
+
*/
|
|
185
|
+
brushConfig: PropTypes.shape({
|
|
186
|
+
enabled: PropTypes.bool,
|
|
187
|
+
preventHighlight: PropTypes.bool,
|
|
188
|
+
preventTooltip: PropTypes.bool
|
|
189
|
+
}),
|
|
182
190
|
children: PropTypes.node,
|
|
183
191
|
className: PropTypes.string,
|
|
184
192
|
/**
|
package/esm/hooks/index.d.ts
CHANGED
|
@@ -17,4 +17,5 @@ export * from "./useLegend.js";
|
|
|
17
17
|
export { useChartGradientId, useChartGradientIdObjectBound } from "./useChartGradientId.js";
|
|
18
18
|
export * from "./animation/index.js";
|
|
19
19
|
export * from "./useChartRootRef.js";
|
|
20
|
-
export * from "./useChartsLocalization.js";
|
|
20
|
+
export * from "./useChartsLocalization.js";
|
|
21
|
+
export * from "./useBrush.js";
|
package/esm/hooks/index.js
CHANGED
|
@@ -17,4 +17,5 @@ export * from "./useLegend.js";
|
|
|
17
17
|
export { useChartGradientId, useChartGradientIdObjectBound } from "./useChartGradientId.js";
|
|
18
18
|
export * from "./animation/index.js";
|
|
19
19
|
export * from "./useChartRootRef.js";
|
|
20
|
-
export * from "./useChartsLocalization.js";
|
|
20
|
+
export * from "./useChartsLocalization.js";
|
|
21
|
+
export * from "./useBrush.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current brush state.
|
|
3
|
+
*
|
|
4
|
+
* - `start` is the starting point of the brush selection.
|
|
5
|
+
* - `current` is the current point of the brush selection.
|
|
6
|
+
*
|
|
7
|
+
* @returns `{ start, current }` - The brush state.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useBrush(): {
|
|
10
|
+
start: {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
};
|
|
14
|
+
current: {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
};
|
|
18
|
+
} | null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { selectorBrushState } from "../internals/plugins/featurePlugins/useChartBrush/index.js";
|
|
2
|
+
import { useSelector } from "../internals/store/useSelector.js";
|
|
3
|
+
import { useStore } from "../internals/store/useStore.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the current brush state.
|
|
7
|
+
*
|
|
8
|
+
* - `start` is the starting point of the brush selection.
|
|
9
|
+
* - `current` is the current point of the brush selection.
|
|
10
|
+
*
|
|
11
|
+
* @returns `{ start, current }` - The brush state.
|
|
12
|
+
*/
|
|
13
|
+
export function useBrush() {
|
|
14
|
+
const store = useStore();
|
|
15
|
+
return useSelector(store, selectorBrushState);
|
|
16
|
+
}
|
package/esm/index.d.ts
CHANGED
|
@@ -28,4 +28,5 @@ export { ChartContainer } from "./ChartContainer/index.js";
|
|
|
28
28
|
export type { ChartContainerProps } from "./ChartContainer/index.js";
|
|
29
29
|
export * from "./ChartDataProvider/index.js";
|
|
30
30
|
export * from "./Toolbar/index.js";
|
|
31
|
-
export * from "./ChartsWrapper/index.js";
|
|
31
|
+
export * from "./ChartsWrapper/index.js";
|
|
32
|
+
export * from "./ChartsBrushOverlay/index.js";
|
package/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-charts v8.
|
|
2
|
+
* @mui/x-charts v8.15.0
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
@@ -35,6 +35,7 @@ export { ChartContainer } from "./ChartContainer/index.js";
|
|
|
35
35
|
export * from "./ChartDataProvider/index.js";
|
|
36
36
|
export * from "./Toolbar/index.js";
|
|
37
37
|
export * from "./ChartsWrapper/index.js";
|
|
38
|
+
export * from "./ChartsBrushOverlay/index.js";
|
|
38
39
|
|
|
39
40
|
// Locales should be imported from `@mui/x-charts/locales`
|
|
40
41
|
// export * from './locales';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export declare function clearStringMeasurementCache(): void;
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
+
* Converts a style object into a string to be used as a cache key
|
|
4
5
|
* @param style React style object
|
|
5
6
|
* @returns CSS styling string
|
|
6
7
|
*/
|
|
7
|
-
export declare
|
|
8
|
+
export declare function getStyleString(style: React.CSSProperties): string;
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
10
11
|
* @param text The string to estimate
|
|
@@ -14,4 +15,8 @@ export declare const getStyleString: (style: React.CSSProperties) => string;
|
|
|
14
15
|
export declare const getStringSize: (text: string | number, style?: React.CSSProperties) => {
|
|
15
16
|
width: number;
|
|
16
17
|
height: number;
|
|
17
|
-
};
|
|
18
|
+
};
|
|
19
|
+
export declare function batchMeasureStrings(texts: Iterable<string | number>, style?: React.CSSProperties): Map<string | number, {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}>;
|
|
@@ -1,60 +1,58 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
// DOM utils
|
|
2
|
+
// DOM utils adapted from
|
|
3
3
|
// https://github.com/recharts/recharts/blob/master/src/util/DOMUtils.ts
|
|
4
4
|
|
|
5
5
|
function isSsr() {
|
|
6
6
|
return typeof window === 'undefined';
|
|
7
7
|
}
|
|
8
8
|
const stringCache = new Map();
|
|
9
|
+
export function clearStringMeasurementCache() {
|
|
10
|
+
stringCache.clear();
|
|
11
|
+
}
|
|
9
12
|
const MAX_CACHE_NUM = 2000;
|
|
10
|
-
const
|
|
11
|
-
position: 'absolute',
|
|
12
|
-
top: '-20000px',
|
|
13
|
-
left: 0,
|
|
14
|
-
padding: 0,
|
|
15
|
-
margin: 0,
|
|
16
|
-
border: 'none',
|
|
17
|
-
whiteSpace: 'pre'
|
|
18
|
-
};
|
|
19
|
-
const STYLE_LIST = ['minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height', 'top', 'left', 'fontSize', 'padding', 'margin', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom'];
|
|
20
|
-
export const MEASUREMENT_SPAN_ID = 'mui_measurement_span';
|
|
13
|
+
const PIXEL_STYLES = new Set(['minWidth', 'maxWidth', 'width', 'minHeight', 'maxHeight', 'height', 'top', 'left', 'fontSize', 'padding', 'margin', 'paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom', 'marginLeft', 'marginRight', 'marginTop', 'marginBottom']);
|
|
21
14
|
|
|
22
15
|
/**
|
|
23
|
-
*
|
|
16
|
+
* Convert number value to pixel value for certain CSS properties
|
|
24
17
|
* @param name CSS property name
|
|
25
18
|
* @param value
|
|
26
19
|
* @returns add 'px' for distance properties
|
|
27
20
|
*/
|
|
28
|
-
function
|
|
29
|
-
if (
|
|
21
|
+
function convertPixelValue(name, value) {
|
|
22
|
+
if (PIXEL_STYLES.has(name) && value === +value) {
|
|
30
23
|
return `${value}px`;
|
|
31
24
|
}
|
|
32
25
|
return value;
|
|
33
26
|
}
|
|
34
27
|
|
|
35
28
|
/**
|
|
36
|
-
*
|
|
29
|
+
* Converts camelcase to dash-case
|
|
37
30
|
* @param text camelcase css property
|
|
38
|
-
* @returns css property
|
|
39
31
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (entry === entry.toUpperCase()) {
|
|
44
|
-
return [...result, '-', entry.toLowerCase()];
|
|
45
|
-
}
|
|
46
|
-
return [...result, entry];
|
|
47
|
-
}, []);
|
|
48
|
-
return formatStrs.join('');
|
|
32
|
+
const AZ = /([A-Z])/g;
|
|
33
|
+
function camelCaseToDashCase(text) {
|
|
34
|
+
return String(text).replace(AZ, match => `-${match.toLowerCase()}`);
|
|
49
35
|
}
|
|
50
36
|
|
|
51
37
|
/**
|
|
52
|
-
*
|
|
38
|
+
* Converts a style object into a string to be used as a cache key
|
|
53
39
|
* @param style React style object
|
|
54
40
|
* @returns CSS styling string
|
|
55
41
|
*/
|
|
56
|
-
export
|
|
57
|
-
let
|
|
42
|
+
export function getStyleString(style) {
|
|
43
|
+
let result = '';
|
|
44
|
+
for (const key in style) {
|
|
45
|
+
if (Object.hasOwn(style, key)) {
|
|
46
|
+
const k = key;
|
|
47
|
+
const value = style[k];
|
|
48
|
+
if (value === undefined) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
result += `${camelCaseToDashCase(k)}:${convertPixelValue(k, value)};`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
58
56
|
|
|
59
57
|
/**
|
|
60
58
|
*
|
|
@@ -69,7 +67,7 @@ export const getStringSize = (text, style = {}) => {
|
|
|
69
67
|
height: 0
|
|
70
68
|
};
|
|
71
69
|
}
|
|
72
|
-
const str =
|
|
70
|
+
const str = String(text);
|
|
73
71
|
const styleString = getStyleString(style);
|
|
74
72
|
const cacheKey = `${str}-${styleString}`;
|
|
75
73
|
const size = stringCache.get(cacheKey);
|
|
@@ -77,22 +75,18 @@ export const getStringSize = (text, style = {}) => {
|
|
|
77
75
|
return size;
|
|
78
76
|
}
|
|
79
77
|
try {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
measurementSpan.setAttribute('id', MEASUREMENT_SPAN_ID);
|
|
84
|
-
measurementSpan.setAttribute('aria-hidden', 'true');
|
|
85
|
-
document.body.appendChild(measurementSpan);
|
|
86
|
-
}
|
|
78
|
+
const measurementSpanContainer = getMeasurementContainer();
|
|
79
|
+
const measurementElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
80
|
+
|
|
87
81
|
// Need to use CSS Object Model (CSSOM) to be able to comply with Content Security Policy (CSP)
|
|
88
82
|
// https://en.wikipedia.org/wiki/Content_Security_Policy
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
measurementSpan.style[camelToMiddleLine(styleKey)] = autoCompleteStyle(styleKey, measurementSpanStyle[styleKey]);
|
|
83
|
+
Object.keys(style).map(styleKey => {
|
|
84
|
+
measurementElem.style[camelCaseToDashCase(styleKey)] = convertPixelValue(styleKey, style[styleKey]);
|
|
92
85
|
return styleKey;
|
|
93
86
|
});
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
measurementElem.textContent = str;
|
|
88
|
+
measurementSpanContainer.replaceChildren(measurementElem);
|
|
89
|
+
const rect = measurementElem.getBoundingClientRect();
|
|
96
90
|
const result = {
|
|
97
91
|
width: rect.width,
|
|
98
92
|
height: rect.height
|
|
@@ -103,15 +97,7 @@ export const getStringSize = (text, style = {}) => {
|
|
|
103
97
|
}
|
|
104
98
|
if (process.env.NODE_ENV === 'test') {
|
|
105
99
|
// In test environment, we clean the measurement span immediately
|
|
106
|
-
|
|
107
|
-
} else {
|
|
108
|
-
if (domCleanTimeout) {
|
|
109
|
-
clearTimeout(domCleanTimeout);
|
|
110
|
-
}
|
|
111
|
-
domCleanTimeout = setTimeout(() => {
|
|
112
|
-
// Limit node cleaning to once per render cycle
|
|
113
|
-
measurementSpan.textContent = '';
|
|
114
|
-
}, 0);
|
|
100
|
+
measurementSpanContainer.replaceChildren();
|
|
115
101
|
}
|
|
116
102
|
return result;
|
|
117
103
|
} catch {
|
|
@@ -120,4 +106,81 @@ export const getStringSize = (text, style = {}) => {
|
|
|
120
106
|
height: 0
|
|
121
107
|
};
|
|
122
108
|
}
|
|
123
|
-
};
|
|
109
|
+
};
|
|
110
|
+
export function batchMeasureStrings(texts, style = {}) {
|
|
111
|
+
if (isSsr()) {
|
|
112
|
+
return new Map(Array.from(texts).map(text => [text, {
|
|
113
|
+
width: 0,
|
|
114
|
+
height: 0
|
|
115
|
+
}]));
|
|
116
|
+
}
|
|
117
|
+
const sizeMap = new Map();
|
|
118
|
+
const textToMeasure = [];
|
|
119
|
+
const styleString = getStyleString(style);
|
|
120
|
+
for (const text of texts) {
|
|
121
|
+
const cacheKey = `${text}-${styleString}`;
|
|
122
|
+
const size = stringCache.get(cacheKey);
|
|
123
|
+
if (size) {
|
|
124
|
+
sizeMap.set(text, size);
|
|
125
|
+
} else {
|
|
126
|
+
textToMeasure.push(text);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const measurementContainer = getMeasurementContainer();
|
|
130
|
+
// Need to use CSS Object Model (CSSOM) to be able to comply with Content Security Policy (CSP)
|
|
131
|
+
// https://en.wikipedia.org/wiki/Content_Security_Policy
|
|
132
|
+
const measurementSpanStyle = _extends({}, style);
|
|
133
|
+
Object.keys(measurementSpanStyle).map(styleKey => {
|
|
134
|
+
measurementContainer.style[camelCaseToDashCase(styleKey)] = convertPixelValue(styleKey, measurementSpanStyle[styleKey]);
|
|
135
|
+
return styleKey;
|
|
136
|
+
});
|
|
137
|
+
const measurementElems = [];
|
|
138
|
+
for (const string of textToMeasure) {
|
|
139
|
+
const measurementElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
140
|
+
measurementElem.textContent = `${string}`;
|
|
141
|
+
measurementElems.push(measurementElem);
|
|
142
|
+
}
|
|
143
|
+
measurementContainer.replaceChildren(...measurementElems);
|
|
144
|
+
for (let i = 0; i < textToMeasure.length; i += 1) {
|
|
145
|
+
const text = textToMeasure[i];
|
|
146
|
+
const measurementSpan = measurementContainer.children[i];
|
|
147
|
+
const rect = measurementSpan.getBoundingClientRect();
|
|
148
|
+
const result = {
|
|
149
|
+
width: rect.width,
|
|
150
|
+
height: rect.height
|
|
151
|
+
};
|
|
152
|
+
const cacheKey = `${text}-${styleString}`;
|
|
153
|
+
stringCache.set(cacheKey, result);
|
|
154
|
+
sizeMap.set(text, result);
|
|
155
|
+
}
|
|
156
|
+
if (stringCache.size + 1 > MAX_CACHE_NUM) {
|
|
157
|
+
stringCache.clear();
|
|
158
|
+
}
|
|
159
|
+
if (process.env.NODE_ENV === 'test') {
|
|
160
|
+
// In test environment, we clean the measurement span immediately
|
|
161
|
+
measurementContainer.replaceChildren();
|
|
162
|
+
}
|
|
163
|
+
return sizeMap;
|
|
164
|
+
}
|
|
165
|
+
let measurementContainer = null;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get (or create) a hidden span element to measure text size.
|
|
169
|
+
*/
|
|
170
|
+
function getMeasurementContainer() {
|
|
171
|
+
if (measurementContainer === null) {
|
|
172
|
+
measurementContainer = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
173
|
+
measurementContainer.setAttribute('aria-hidden', 'true');
|
|
174
|
+
measurementContainer.style.position = 'absolute';
|
|
175
|
+
measurementContainer.style.top = '-20000px';
|
|
176
|
+
measurementContainer.style.left = '0';
|
|
177
|
+
measurementContainer.style.padding = '0';
|
|
178
|
+
measurementContainer.style.margin = '0';
|
|
179
|
+
measurementContainer.style.border = 'none';
|
|
180
|
+
measurementContainer.style.pointerEvents = 'none';
|
|
181
|
+
measurementContainer.style.visibility = 'hidden';
|
|
182
|
+
measurementContainer.style.contain = 'strict';
|
|
183
|
+
document.body.appendChild(measurementContainer);
|
|
184
|
+
}
|
|
185
|
+
return measurementContainer;
|
|
186
|
+
}
|