@mui/x-charts-pro 8.5.0 → 8.5.2
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/BarChartPro/BarChartPro.d.ts +3 -2
- package/BarChartPro/BarChartPro.js +1 -1
- package/CHANGELOG.md +204 -0
- package/ChartContainerPro/ChartProApi.d.ts +2 -0
- package/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
- package/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.d.ts +0 -2
- package/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.js +42 -9
- package/ChartZoomSlider/internals/ChartAxisZoomSliderTrack.js +0 -22
- package/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -4
- package/ChartsToolbarPro/ChartsToolbarPro.js +7 -13
- package/ChartsToolbarPro/{ChartsToolbarZoomInButton.d.ts → ChartsToolbarZoomInTrigger.d.ts} +6 -5
- package/ChartsToolbarPro/{ChartsToolbarZoomInButton.js → ChartsToolbarZoomInTrigger.js} +7 -6
- package/ChartsToolbarPro/{ChartsToolbarZoomOutButton.d.ts → ChartsToolbarZoomOutTrigger.d.ts} +6 -5
- package/ChartsToolbarPro/{ChartsToolbarZoomOutButton.js → ChartsToolbarZoomOutTrigger.js} +7 -6
- package/ChartsToolbarPro/Toolbar.types.d.ts +15 -0
- package/ChartsToolbarPro/Toolbar.types.js +5 -0
- package/ChartsToolbarPro/index.d.ts +2 -2
- package/ChartsToolbarPro/index.js +8 -8
- package/FunnelChart/FunnelChart.js +4 -11
- package/FunnelChart/FunnelChart.plugins.d.ts +3 -2
- package/FunnelChart/FunnelChart.plugins.js +2 -1
- package/FunnelChart/FunnelPlot.d.ts +0 -5
- package/FunnelChart/FunnelPlot.js +40 -50
- package/FunnelChart/FunnelSection.d.ts +1 -1
- package/FunnelChart/FunnelSectionLabel.d.ts +21 -0
- package/FunnelChart/FunnelSectionLabel.js +52 -0
- package/FunnelChart/categoryAxis.types.d.ts +2 -1
- package/FunnelChart/curves/bump.d.ts +9 -5
- package/FunnelChart/curves/bump.js +72 -43
- package/FunnelChart/curves/curve.types.d.ts +6 -1
- package/FunnelChart/curves/getFunnelCurve.js +3 -0
- package/FunnelChart/curves/linear.d.ts +10 -2
- package/FunnelChart/curves/linear.js +97 -17
- package/FunnelChart/curves/pyramid.js +10 -14
- package/FunnelChart/curves/step-pyramid.js +4 -6
- package/FunnelChart/curves/step.js +1 -15
- package/FunnelChart/funnel.types.d.ts +1 -0
- package/FunnelChart/funnelAxisPlugin/computeAxisValue.d.ts +25 -0
- package/FunnelChart/funnelAxisPlugin/computeAxisValue.js +124 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.d.ts +3 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.js +173 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.types.d.ts +27 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.types.js +5 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.d.ts +1482 -0
- package/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.js +27 -0
- package/FunnelChart/funnelPlotSlots.types.d.ts +11 -0
- package/FunnelChart/funnelSectionClasses.d.ts +2 -0
- package/FunnelChart/funnelSectionClasses.js +17 -4
- package/FunnelChart/index.d.ts +3 -1
- package/FunnelChart/index.js +18 -2
- package/FunnelChart/labelUtils.d.ts +3 -2
- package/FunnelChart/labelUtils.js +15 -15
- package/FunnelChart/positionGetter.d.ts +1 -0
- package/FunnelChart/positionGetter.js +5 -0
- package/FunnelChart/useFunnelChartProps.js +1 -3
- package/Heatmap/Heatmap.d.ts +8 -3
- package/Heatmap/Heatmap.js +10 -2
- package/Heatmap/HeatmapTooltip/HeatmapTooltipAxesValue.d.ts +1 -1
- package/LineChartPro/LineChartPro.d.ts +3 -2
- package/LineChartPro/LineChartPro.js +1 -1
- package/PieChartPro/PieChartPro.d.ts +22 -0
- package/PieChartPro/PieChartPro.js +204 -0
- package/PieChartPro/PieChartPro.plugins.d.ts +4 -0
- package/PieChartPro/PieChartPro.plugins.js +9 -0
- package/PieChartPro/index.d.ts +1 -0
- package/PieChartPro/index.js +16 -0
- package/RadarChartPro/RadarChartPro.d.ts +17 -2
- package/RadarChartPro/RadarChartPro.js +1 -1
- package/ScatterChartPro/ScatterChartPro.d.ts +3 -2
- package/ScatterChartPro/ScatterChartPro.js +1 -1
- package/esm/BarChartPro/BarChartPro.d.ts +3 -2
- package/esm/BarChartPro/BarChartPro.js +1 -1
- package/esm/ChartContainerPro/ChartProApi.d.ts +2 -0
- package/esm/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
- package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.d.ts +0 -2
- package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.js +43 -10
- package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderTrack.js +0 -22
- package/esm/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -4
- package/esm/ChartsToolbarPro/ChartsToolbarPro.js +8 -14
- package/esm/ChartsToolbarPro/{ChartsToolbarZoomInButton.d.ts → ChartsToolbarZoomInTrigger.d.ts} +6 -5
- package/esm/ChartsToolbarPro/{ChartsToolbarZoomInButton.js → ChartsToolbarZoomInTrigger.js} +8 -7
- package/esm/ChartsToolbarPro/{ChartsToolbarZoomOutButton.d.ts → ChartsToolbarZoomOutTrigger.d.ts} +6 -5
- package/esm/ChartsToolbarPro/{ChartsToolbarZoomOutButton.js → ChartsToolbarZoomOutTrigger.js} +8 -7
- package/esm/ChartsToolbarPro/Toolbar.types.d.ts +15 -0
- package/esm/ChartsToolbarPro/Toolbar.types.js +1 -0
- package/esm/ChartsToolbarPro/index.d.ts +2 -2
- package/esm/ChartsToolbarPro/index.js +2 -2
- package/esm/FunnelChart/FunnelChart.js +4 -11
- package/esm/FunnelChart/FunnelChart.plugins.d.ts +3 -2
- package/esm/FunnelChart/FunnelChart.plugins.js +3 -2
- package/esm/FunnelChart/FunnelPlot.d.ts +0 -5
- package/esm/FunnelChart/FunnelPlot.js +41 -51
- package/esm/FunnelChart/FunnelSection.d.ts +1 -1
- package/esm/FunnelChart/FunnelSectionLabel.d.ts +21 -0
- package/esm/FunnelChart/FunnelSectionLabel.js +46 -0
- package/esm/FunnelChart/categoryAxis.types.d.ts +2 -1
- package/esm/FunnelChart/curves/bump.d.ts +9 -5
- package/esm/FunnelChart/curves/bump.js +72 -43
- package/esm/FunnelChart/curves/curve.types.d.ts +6 -1
- package/esm/FunnelChart/curves/getFunnelCurve.js +3 -0
- package/esm/FunnelChart/curves/linear.d.ts +10 -2
- package/esm/FunnelChart/curves/linear.js +97 -17
- package/esm/FunnelChart/curves/pyramid.js +10 -14
- package/esm/FunnelChart/curves/step-pyramid.js +4 -6
- package/esm/FunnelChart/curves/step.js +1 -15
- package/esm/FunnelChart/funnel.types.d.ts +1 -0
- package/esm/FunnelChart/funnelAxisPlugin/computeAxisValue.d.ts +25 -0
- package/esm/FunnelChart/funnelAxisPlugin/computeAxisValue.js +114 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.d.ts +3 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.js +165 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.types.d.ts +27 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxis.types.js +1 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.d.ts +1482 -0
- package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.js +20 -0
- package/esm/FunnelChart/funnelPlotSlots.types.d.ts +11 -0
- package/esm/FunnelChart/funnelSectionClasses.d.ts +2 -0
- package/esm/FunnelChart/funnelSectionClasses.js +15 -3
- package/esm/FunnelChart/index.d.ts +3 -1
- package/esm/FunnelChart/index.js +3 -1
- package/esm/FunnelChart/labelUtils.d.ts +3 -2
- package/esm/FunnelChart/labelUtils.js +15 -15
- package/esm/FunnelChart/positionGetter.d.ts +1 -0
- package/esm/FunnelChart/positionGetter.js +1 -0
- package/esm/FunnelChart/useFunnelChartProps.js +1 -3
- package/esm/Heatmap/Heatmap.d.ts +8 -3
- package/esm/Heatmap/Heatmap.js +10 -2
- package/esm/Heatmap/HeatmapTooltip/HeatmapTooltipAxesValue.d.ts +1 -1
- package/esm/LineChartPro/LineChartPro.d.ts +3 -2
- package/esm/LineChartPro/LineChartPro.js +1 -1
- package/esm/PieChartPro/PieChartPro.d.ts +22 -0
- package/esm/PieChartPro/PieChartPro.js +197 -0
- package/esm/PieChartPro/PieChartPro.plugins.d.ts +4 -0
- package/esm/PieChartPro/PieChartPro.plugins.js +3 -0
- package/esm/PieChartPro/index.d.ts +1 -0
- package/esm/PieChartPro/index.js +1 -0
- package/esm/RadarChartPro/RadarChartPro.d.ts +17 -2
- package/esm/RadarChartPro/RadarChartPro.js +1 -1
- package/esm/ScatterChartPro/ScatterChartPro.d.ts +3 -2
- package/esm/ScatterChartPro/ScatterChartPro.js +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.js +2 -1
- package/index.d.ts +1 -0
- package/index.js +12 -1
- package/package.json +7 -7
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
2
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
const _excluded = ["onItemClick"
|
|
3
|
+
const _excluded = ["onItemClick"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import { line as d3Line } from '@mui/x-charts-vendor/d3-shape';
|
|
7
|
-
import { cartesianSeriesTypes } from '@mui/x-charts/internals';
|
|
8
|
-
import { useXAxes, useYAxes } from '@mui/x-charts/hooks';
|
|
9
|
-
import { useTheme } from '@mui/material/styles';
|
|
7
|
+
import { cartesianSeriesTypes, useSelector, useStore, isBandScale } from '@mui/x-charts/internals';
|
|
10
8
|
import { FunnelSection } from "./FunnelSection.js";
|
|
11
9
|
import { alignLabel, positionLabel } from "./labelUtils.js";
|
|
12
10
|
import { useFunnelSeriesContext } from "../hooks/useFunnelSeries.js";
|
|
13
11
|
import { getFunnelCurve } from "./curves/index.js";
|
|
12
|
+
import { FunnelSectionLabel } from "./FunnelSectionLabel.js";
|
|
13
|
+
import { selectorChartXAxis, selectorChartYAxis, selectorFunnelGap } from "./funnelAxisPlugin/useChartFunnelAxisRendering.selectors.js";
|
|
14
14
|
import { createElement as _createElement } from "react";
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
cartesianSeriesTypes.addType('funnel');
|
|
17
|
-
const useAggregatedData =
|
|
17
|
+
const useAggregatedData = () => {
|
|
18
18
|
const seriesData = useFunnelSeriesContext();
|
|
19
|
+
const store = useStore();
|
|
19
20
|
const {
|
|
20
|
-
xAxis,
|
|
21
|
-
xAxisIds
|
|
22
|
-
} =
|
|
21
|
+
axis: xAxis,
|
|
22
|
+
axisIds: xAxisIds
|
|
23
|
+
} = useSelector(store, selectorChartXAxis);
|
|
23
24
|
const {
|
|
24
|
-
yAxis,
|
|
25
|
-
yAxisIds
|
|
26
|
-
} =
|
|
25
|
+
axis: yAxis,
|
|
26
|
+
axisIds: yAxisIds
|
|
27
|
+
} = useSelector(store, selectorChartYAxis);
|
|
28
|
+
const gap = useSelector(store, selectorFunnelGap);
|
|
27
29
|
const allData = React.useMemo(() => {
|
|
28
30
|
if (seriesData === undefined) {
|
|
29
31
|
return [];
|
|
@@ -46,22 +48,28 @@ const useAggregatedData = gap => {
|
|
|
46
48
|
const bandWidth = (isXAxisBand || isYAxisBand) && baseScaleConfig.scale?.bandwidth() || 0;
|
|
47
49
|
const xScale = xAxis[xAxisId].scale;
|
|
48
50
|
const yScale = yAxis[yAxisId].scale;
|
|
49
|
-
const xPosition = (value, bandIndex, stackOffset, useBand) => {
|
|
50
|
-
if (
|
|
51
|
-
const position = xScale(
|
|
51
|
+
const xPosition = (value, bandIndex, bandIdentifier, stackOffset, useBand) => {
|
|
52
|
+
if (isBandScale(xScale)) {
|
|
53
|
+
const position = xScale(bandIdentifier);
|
|
52
54
|
return useBand ? position + bandWidth : position;
|
|
53
55
|
}
|
|
54
|
-
|
|
56
|
+
if (isHorizontal) {
|
|
57
|
+
return xScale(value + (stackOffset || 0)) + bandIndex * gap;
|
|
58
|
+
}
|
|
59
|
+
return xScale(value);
|
|
55
60
|
};
|
|
56
|
-
const yPosition = (value, bandIndex, stackOffset, useBand) => {
|
|
57
|
-
if (
|
|
58
|
-
const position = yScale(
|
|
61
|
+
const yPosition = (value, bandIndex, bandIdentifier, stackOffset, useBand) => {
|
|
62
|
+
if (isBandScale(yScale)) {
|
|
63
|
+
const position = yScale(bandIdentifier);
|
|
59
64
|
return useBand ? position + bandWidth : position;
|
|
60
65
|
}
|
|
61
|
-
|
|
66
|
+
if (isHorizontal) {
|
|
67
|
+
return yScale(value);
|
|
68
|
+
}
|
|
69
|
+
return yScale(value + (stackOffset || 0)) + bandIndex * gap;
|
|
62
70
|
};
|
|
63
|
-
const allY = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => yPosition(v.y, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
|
|
64
|
-
const allX = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => xPosition(v.x, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
|
|
71
|
+
const allY = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => yPosition(v.y, dataIndex, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
|
|
72
|
+
const allX = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => xPosition(v.x, dataIndex, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
|
|
65
73
|
const minPoint = {
|
|
66
74
|
x: Math.min(...allX),
|
|
67
75
|
y: Math.min(...allY)
|
|
@@ -89,7 +97,7 @@ const useAggregatedData = gap => {
|
|
|
89
97
|
min: minPoint,
|
|
90
98
|
max: maxPoint
|
|
91
99
|
});
|
|
92
|
-
const line = d3Line().x(d => xPosition(d.x, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).y(d => yPosition(d.y, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).curve(curve);
|
|
100
|
+
const line = d3Line().x(d => xPosition(d.x, dataIndex, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).y(d => yPosition(d.y, dataIndex, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).curve(curve);
|
|
93
101
|
return {
|
|
94
102
|
d: line(values),
|
|
95
103
|
color,
|
|
@@ -118,12 +126,10 @@ const useAggregatedData = gap => {
|
|
|
118
126
|
};
|
|
119
127
|
function FunnelPlot(props) {
|
|
120
128
|
const {
|
|
121
|
-
onItemClick
|
|
122
|
-
gap
|
|
129
|
+
onItemClick
|
|
123
130
|
} = props,
|
|
124
131
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
125
|
-
const
|
|
126
|
-
const data = useAggregatedData(gap);
|
|
132
|
+
const data = useAggregatedData();
|
|
127
133
|
return /*#__PURE__*/_jsxs(React.Fragment, {
|
|
128
134
|
children: [data.map(({
|
|
129
135
|
d,
|
|
@@ -148,29 +154,18 @@ function FunnelPlot(props) {
|
|
|
148
154
|
})
|
|
149
155
|
}))), data.map(({
|
|
150
156
|
id,
|
|
151
|
-
label
|
|
157
|
+
label,
|
|
158
|
+
seriesId,
|
|
159
|
+
dataIndex
|
|
152
160
|
}) => {
|
|
153
|
-
if (!label) {
|
|
161
|
+
if (!label || !label.value) {
|
|
154
162
|
return null;
|
|
155
163
|
}
|
|
156
|
-
return /*#__PURE__*/_jsx(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
stroke: "none",
|
|
162
|
-
pointerEvents: "none",
|
|
163
|
-
fontFamily: theme.typography.body2.fontFamily,
|
|
164
|
-
fontSize: theme.typography.body2.fontSize,
|
|
165
|
-
fontSizeAdjust: theme.typography.body2.fontSizeAdjust,
|
|
166
|
-
fontWeight: theme.typography.body2.fontWeight,
|
|
167
|
-
letterSpacing: theme.typography.body2.letterSpacing,
|
|
168
|
-
fontStretch: theme.typography.body2.fontStretch,
|
|
169
|
-
fontStyle: theme.typography.body2.fontStyle,
|
|
170
|
-
fontVariant: theme.typography.body2.fontVariant,
|
|
171
|
-
fill: (theme.vars || theme)?.palette?.text?.primary,
|
|
172
|
-
children: label.value
|
|
173
|
-
}, id);
|
|
164
|
+
return /*#__PURE__*/_jsx(FunnelSectionLabel, _extends({
|
|
165
|
+
label: label,
|
|
166
|
+
dataIndex: dataIndex,
|
|
167
|
+
seriesId: seriesId
|
|
168
|
+
}, other), id);
|
|
174
169
|
})]
|
|
175
170
|
});
|
|
176
171
|
}
|
|
@@ -179,11 +174,6 @@ process.env.NODE_ENV !== "production" ? FunnelPlot.propTypes = {
|
|
|
179
174
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
180
175
|
// | To update them edit the TypeScript types and run "pnpm proptypes" |
|
|
181
176
|
// ----------------------------------------------------------------------
|
|
182
|
-
/**
|
|
183
|
-
* The gap, in pixels, between funnel sections.
|
|
184
|
-
* @default 0
|
|
185
|
-
*/
|
|
186
|
-
gap: PropTypes.number,
|
|
187
177
|
/**
|
|
188
178
|
* Callback fired when a funnel item is clicked.
|
|
189
179
|
* @param {React.MouseEvent<SVGElement, MouseEvent>} event The event source of the callback.
|
|
@@ -8,7 +8,7 @@ export interface FunnelSectionProps extends Omit<React.SVGProps<SVGPathElement>,
|
|
|
8
8
|
classes?: Partial<FunnelSectionClasses>;
|
|
9
9
|
variant?: 'filled' | 'outlined';
|
|
10
10
|
}
|
|
11
|
-
export declare const FunnelSectionPath: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, React.SVGProps<SVGPathElement>, {}>;
|
|
11
|
+
export declare const FunnelSectionPath: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, React.SVGProps<SVGPathElement>, {}>;
|
|
12
12
|
/**
|
|
13
13
|
* @ignore - internal component.
|
|
14
14
|
*/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { SeriesId } from '@mui/x-charts/internals';
|
|
3
|
+
import { FunnelSectionClasses } from "./funnelSectionClasses.js";
|
|
4
|
+
export interface FunnelSectionLabelConfig {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
value: string | null;
|
|
8
|
+
textAnchor?: React.SVGProps<SVGTextElement>['textAnchor'];
|
|
9
|
+
dominantBaseline?: React.SVGProps<SVGTextElement>['dominantBaseline'];
|
|
10
|
+
}
|
|
11
|
+
export interface FunnelSectionLabelProps extends Omit<React.SVGProps<SVGTextElement>, 'ref' | 'id'> {
|
|
12
|
+
classes?: Partial<FunnelSectionClasses>;
|
|
13
|
+
label: FunnelSectionLabelConfig;
|
|
14
|
+
seriesId: SeriesId;
|
|
15
|
+
dataIndex: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @ignore - internal component.
|
|
19
|
+
*/
|
|
20
|
+
declare const FunnelSectionLabel: React.ForwardRefExoticComponent<FunnelSectionLabelProps & React.RefAttributes<{}>>;
|
|
21
|
+
export { FunnelSectionLabel };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
|
+
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
5
|
+
const _excluded = ["classes", "color", "onClick", "className", "label", "seriesId", "dataIndex"];
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
import { useTheme } from '@mui/material/styles';
|
|
8
|
+
import { consumeSlots } from '@mui/x-charts/internals';
|
|
9
|
+
import { useLabelUtilityClasses } from "./funnelSectionClasses.js";
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
/**
|
|
12
|
+
* @ignore - internal component.
|
|
13
|
+
*/
|
|
14
|
+
const FunnelSectionLabel = consumeSlots('MuiFunnelSectionLabel', 'funnelSectionLabel', {
|
|
15
|
+
classesResolver: useLabelUtilityClasses
|
|
16
|
+
}, /*#__PURE__*/React.forwardRef(function FunnelSectionLabel(props, ref) {
|
|
17
|
+
const {
|
|
18
|
+
classes,
|
|
19
|
+
label
|
|
20
|
+
} = props,
|
|
21
|
+
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
22
|
+
const theme = useTheme();
|
|
23
|
+
return /*#__PURE__*/_jsx("text", _extends({
|
|
24
|
+
stroke: "none",
|
|
25
|
+
pointerEvents: "none",
|
|
26
|
+
fontFamily: theme.typography.body2.fontFamily,
|
|
27
|
+
fontSize: theme.typography.body2.fontSize,
|
|
28
|
+
fontSizeAdjust: theme.typography.body2.fontSizeAdjust,
|
|
29
|
+
fontWeight: theme.typography.body2.fontWeight,
|
|
30
|
+
letterSpacing: theme.typography.body2.letterSpacing,
|
|
31
|
+
fontStretch: theme.typography.body2.fontStretch,
|
|
32
|
+
fontStyle: theme.typography.body2.fontStyle,
|
|
33
|
+
fontVariant: theme.typography.body2.fontVariant,
|
|
34
|
+
fill: (theme.vars || theme)?.palette?.text?.primary,
|
|
35
|
+
className: classes?.label,
|
|
36
|
+
x: label.x,
|
|
37
|
+
y: label.y,
|
|
38
|
+
textAnchor: label.textAnchor ?? 'middle',
|
|
39
|
+
dominantBaseline: label.dominantBaseline ?? 'central'
|
|
40
|
+
}, other, {
|
|
41
|
+
ref: ref,
|
|
42
|
+
children: label.value
|
|
43
|
+
}));
|
|
44
|
+
}));
|
|
45
|
+
if (process.env.NODE_ENV !== "production") FunnelSectionLabel.displayName = "FunnelSectionLabel";
|
|
46
|
+
export { FunnelSectionLabel };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AxisConfig, ScaleName } from '@mui/x-charts/models';
|
|
2
2
|
import { MakeOptional } from '@mui/x-internals/types';
|
|
3
|
-
export type
|
|
3
|
+
export type FunnelScaleName = Exclude<ScaleName, 'point'>;
|
|
4
|
+
export type CategoryAxis<S extends FunnelScaleName = FunnelScaleName> = S extends FunnelScaleName ? {
|
|
4
5
|
/**
|
|
5
6
|
* The categories to be displayed on the axis.
|
|
6
7
|
* The order of the categories is the order in which they are displayed.
|
|
@@ -10,18 +10,22 @@ import { CurveOptions } from "./curve.types.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class Bump implements CurveGenerator {
|
|
12
12
|
private context;
|
|
13
|
-
private x;
|
|
14
|
-
private y;
|
|
15
|
-
private currentPoint;
|
|
16
13
|
private isHorizontal;
|
|
17
|
-
private
|
|
14
|
+
private min;
|
|
15
|
+
private max;
|
|
16
|
+
private points;
|
|
18
17
|
constructor(context: CanvasRenderingContext2D, {
|
|
19
18
|
isHorizontal,
|
|
20
|
-
|
|
19
|
+
min,
|
|
20
|
+
max,
|
|
21
|
+
isIncreasing
|
|
21
22
|
}: CurveOptions);
|
|
22
23
|
areaStart(): void;
|
|
23
24
|
areaEnd(): void;
|
|
24
25
|
lineStart(): void;
|
|
25
26
|
lineEnd(): void;
|
|
26
27
|
point(x: number, y: number): void;
|
|
28
|
+
private drawPath;
|
|
29
|
+
private drawHorizontalPath;
|
|
30
|
+
private drawVerticalPath;
|
|
27
31
|
}
|
|
@@ -11,64 +11,93 @@
|
|
|
11
11
|
export class Bump {
|
|
12
12
|
constructor(context, {
|
|
13
13
|
isHorizontal,
|
|
14
|
-
|
|
14
|
+
min,
|
|
15
|
+
max,
|
|
16
|
+
isIncreasing
|
|
15
17
|
}) {
|
|
16
18
|
this.context = void 0;
|
|
17
|
-
this.x = NaN;
|
|
18
|
-
this.y = NaN;
|
|
19
|
-
this.currentPoint = 0;
|
|
20
19
|
this.isHorizontal = false;
|
|
21
|
-
this.
|
|
20
|
+
this.min = {
|
|
21
|
+
x: 0,
|
|
22
|
+
y: 0
|
|
23
|
+
};
|
|
24
|
+
this.max = {
|
|
25
|
+
x: 0,
|
|
26
|
+
y: 0
|
|
27
|
+
};
|
|
28
|
+
this.points = [];
|
|
22
29
|
this.context = context;
|
|
23
30
|
this.isHorizontal = isHorizontal ?? false;
|
|
24
|
-
this.
|
|
31
|
+
this.min = min ?? {
|
|
32
|
+
x: 0,
|
|
33
|
+
y: 0
|
|
34
|
+
};
|
|
35
|
+
this.max = max ?? {
|
|
36
|
+
x: 0,
|
|
37
|
+
y: 0
|
|
38
|
+
};
|
|
39
|
+
if (isIncreasing) {
|
|
40
|
+
const currentMin = this.min;
|
|
41
|
+
const currentMax = this.max;
|
|
42
|
+
this.min = currentMax;
|
|
43
|
+
this.max = currentMin;
|
|
44
|
+
}
|
|
25
45
|
}
|
|
26
46
|
areaStart() {}
|
|
27
47
|
areaEnd() {}
|
|
28
48
|
lineStart() {}
|
|
29
49
|
lineEnd() {}
|
|
30
50
|
point(x, y) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (this.
|
|
36
|
-
if (this.currentPoint === 0) {
|
|
37
|
-
this.context.moveTo(x + this.gap, y);
|
|
38
|
-
this.context.lineTo(x + this.gap, y);
|
|
39
|
-
} else if (this.currentPoint === 1) {
|
|
40
|
-
this.context.bezierCurveTo((this.x + x) / 2, this.y, (this.x + x) / 2, y, x - this.gap, y);
|
|
41
|
-
} else if (this.currentPoint === 2) {
|
|
42
|
-
this.context.lineTo(x - this.gap, y);
|
|
43
|
-
} else {
|
|
44
|
-
this.context.bezierCurveTo((this.x + x) / 2, this.y, (this.x + x) / 2, y, x + this.gap, y);
|
|
45
|
-
}
|
|
46
|
-
if (this.currentPoint === 3) {
|
|
47
|
-
this.context.closePath();
|
|
48
|
-
}
|
|
49
|
-
this.currentPoint += 1;
|
|
50
|
-
this.x = x;
|
|
51
|
-
this.y = y;
|
|
51
|
+
this.points.push({
|
|
52
|
+
x,
|
|
53
|
+
y
|
|
54
|
+
});
|
|
55
|
+
if (this.points.length < 4) {
|
|
52
56
|
return;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.context.bezierCurveTo(this.x, (this.y + y) / 2, x, (this.y + y) / 2, x, y - this.gap);
|
|
62
|
-
} else if (this.currentPoint === 2) {
|
|
63
|
-
this.context.lineTo(x, y - this.gap);
|
|
59
|
+
// Draw the path using bezier curves
|
|
60
|
+
this.drawPath();
|
|
61
|
+
}
|
|
62
|
+
drawPath() {
|
|
63
|
+
if (this.isHorizontal) {
|
|
64
|
+
this.drawHorizontalPath();
|
|
64
65
|
} else {
|
|
65
|
-
this.
|
|
66
|
-
}
|
|
67
|
-
if (this.currentPoint === 3) {
|
|
68
|
-
this.context.closePath();
|
|
66
|
+
this.drawVerticalPath();
|
|
69
67
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
}
|
|
69
|
+
drawHorizontalPath() {
|
|
70
|
+
const [p0, p1, p2, p3] = this.points;
|
|
71
|
+
|
|
72
|
+
// 0 is the top-left corner
|
|
73
|
+
this.context.moveTo(p0.x, p0.y);
|
|
74
|
+
this.context.lineTo(p0.x, p0.y);
|
|
75
|
+
|
|
76
|
+
// Bezier curve to point 1
|
|
77
|
+
this.context.bezierCurveTo((p0.x + p1.x) / 2, p0.y, (p0.x + p1.x) / 2, p1.y, p1.x, p1.y);
|
|
78
|
+
|
|
79
|
+
// Line to point 2
|
|
80
|
+
this.context.lineTo(p2.x, p2.y);
|
|
81
|
+
|
|
82
|
+
// Bezier curve back to point 3
|
|
83
|
+
this.context.bezierCurveTo((p2.x + p3.x) / 2, p2.y, (p2.x + p3.x) / 2, p3.y, p3.x, p3.y);
|
|
84
|
+
this.context.closePath();
|
|
85
|
+
}
|
|
86
|
+
drawVerticalPath() {
|
|
87
|
+
const [p0, p1, p2, p3] = this.points;
|
|
88
|
+
|
|
89
|
+
// 0 is the top-right corner
|
|
90
|
+
this.context.moveTo(p0.x, p0.y);
|
|
91
|
+
this.context.lineTo(p0.x, p0.y);
|
|
92
|
+
|
|
93
|
+
// Bezier curve to point 1
|
|
94
|
+
this.context.bezierCurveTo(p0.x, (p0.y + p1.y) / 2, p1.x, (p0.y + p1.y) / 2, p1.x, p1.y);
|
|
95
|
+
|
|
96
|
+
// Line to point 2
|
|
97
|
+
this.context.lineTo(p2.x, p2.y);
|
|
98
|
+
|
|
99
|
+
// Bezier curve back to point 3
|
|
100
|
+
this.context.bezierCurveTo(p2.x, (p2.y + p3.y) / 2, p3.x, (p2.y + p3.y) / 2, p3.x, p3.y);
|
|
101
|
+
this.context.closePath();
|
|
73
102
|
}
|
|
74
103
|
}
|
|
@@ -34,8 +34,13 @@ export type CurveOptions = {
|
|
|
34
34
|
* The maximum point for all the segments.
|
|
35
35
|
*/
|
|
36
36
|
max?: Point;
|
|
37
|
+
/**
|
|
38
|
+
* The shape of the point of the funnel for the curves that support it.
|
|
39
|
+
*/
|
|
40
|
+
pointShape?: FunnelPointShape;
|
|
37
41
|
};
|
|
38
|
-
export type FunnelCurveType = 'linear' | 'step' | 'bump' | 'pyramid' | 'step-pyramid';
|
|
42
|
+
export type FunnelCurveType = 'linear' | 'linear-sharp' | 'step' | 'bump' | 'pyramid' | 'step-pyramid';
|
|
43
|
+
export type FunnelPointShape = 'square' | 'sharp';
|
|
39
44
|
export type Point = {
|
|
40
45
|
x: number;
|
|
41
46
|
y: number;
|
|
@@ -19,5 +19,8 @@ const curveConstructor = curve => {
|
|
|
19
19
|
return Linear;
|
|
20
20
|
};
|
|
21
21
|
export const getFunnelCurve = (curve, options) => {
|
|
22
|
+
if (curve === 'linear-sharp') {
|
|
23
|
+
options.pointShape = 'sharp';
|
|
24
|
+
}
|
|
22
25
|
return context => new (curveConstructor(curve))(context, options);
|
|
23
26
|
};
|
|
@@ -3,7 +3,7 @@ import { CurveOptions } from "./curve.types.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* This is a custom "linear" curve generator.
|
|
5
5
|
* It draws straight lines for the 4 provided points,
|
|
6
|
-
* with the option to
|
|
6
|
+
* with the option to properly handling the border radius.
|
|
7
7
|
*
|
|
8
8
|
* The implementation is based on the d3-shape linear curve generator.
|
|
9
9
|
* https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/linear.js
|
|
@@ -13,15 +13,23 @@ export declare class Linear implements CurveGenerator {
|
|
|
13
13
|
private position;
|
|
14
14
|
private sections;
|
|
15
15
|
private isHorizontal;
|
|
16
|
+
private isIncreasing;
|
|
16
17
|
private gap;
|
|
17
18
|
private borderRadius;
|
|
19
|
+
private min;
|
|
20
|
+
private max;
|
|
18
21
|
private points;
|
|
22
|
+
private pointShape;
|
|
19
23
|
constructor(context: CanvasRenderingContext2D, {
|
|
20
24
|
isHorizontal,
|
|
21
25
|
gap,
|
|
22
26
|
position,
|
|
23
27
|
sections,
|
|
24
|
-
borderRadius
|
|
28
|
+
borderRadius,
|
|
29
|
+
min,
|
|
30
|
+
max,
|
|
31
|
+
isIncreasing,
|
|
32
|
+
pointShape
|
|
25
33
|
}: CurveOptions);
|
|
26
34
|
areaStart(): void;
|
|
27
35
|
areaEnd(): void;
|
|
@@ -6,7 +6,7 @@ import { lerpX, lerpY } from "./utils.js";
|
|
|
6
6
|
/**
|
|
7
7
|
* This is a custom "linear" curve generator.
|
|
8
8
|
* It draws straight lines for the 4 provided points,
|
|
9
|
-
* with the option to
|
|
9
|
+
* with the option to properly handling the border radius.
|
|
10
10
|
*
|
|
11
11
|
* The implementation is based on the d3-shape linear curve generator.
|
|
12
12
|
* https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/linear.js
|
|
@@ -17,21 +17,51 @@ export class Linear {
|
|
|
17
17
|
gap,
|
|
18
18
|
position,
|
|
19
19
|
sections,
|
|
20
|
-
borderRadius
|
|
20
|
+
borderRadius,
|
|
21
|
+
min,
|
|
22
|
+
max,
|
|
23
|
+
isIncreasing,
|
|
24
|
+
pointShape
|
|
21
25
|
}) {
|
|
22
26
|
this.context = void 0;
|
|
23
27
|
this.position = 0;
|
|
24
28
|
this.sections = 0;
|
|
25
29
|
this.isHorizontal = false;
|
|
30
|
+
this.isIncreasing = false;
|
|
26
31
|
this.gap = 0;
|
|
27
32
|
this.borderRadius = 0;
|
|
33
|
+
this.min = {
|
|
34
|
+
x: 0,
|
|
35
|
+
y: 0
|
|
36
|
+
};
|
|
37
|
+
this.max = {
|
|
38
|
+
x: 0,
|
|
39
|
+
y: 0
|
|
40
|
+
};
|
|
28
41
|
this.points = [];
|
|
42
|
+
this.pointShape = 'square';
|
|
29
43
|
this.context = context;
|
|
30
44
|
this.isHorizontal = isHorizontal ?? false;
|
|
31
|
-
this.gap =
|
|
45
|
+
this.gap = gap ?? 0;
|
|
32
46
|
this.position = position ?? 0;
|
|
33
47
|
this.sections = sections ?? 1;
|
|
34
48
|
this.borderRadius = borderRadius ?? 0;
|
|
49
|
+
this.isIncreasing = isIncreasing ?? false;
|
|
50
|
+
this.min = min ?? {
|
|
51
|
+
x: 0,
|
|
52
|
+
y: 0
|
|
53
|
+
};
|
|
54
|
+
this.max = max ?? {
|
|
55
|
+
x: 0,
|
|
56
|
+
y: 0
|
|
57
|
+
};
|
|
58
|
+
this.pointShape = pointShape ?? 'square';
|
|
59
|
+
if (isIncreasing) {
|
|
60
|
+
const currentMin = this.min;
|
|
61
|
+
const currentMax = this.max;
|
|
62
|
+
this.min = currentMax;
|
|
63
|
+
this.max = currentMin;
|
|
64
|
+
}
|
|
35
65
|
}
|
|
36
66
|
areaStart() {}
|
|
37
67
|
areaEnd() {}
|
|
@@ -41,11 +71,34 @@ export class Linear {
|
|
|
41
71
|
if (this.gap > 0) {
|
|
42
72
|
return this.borderRadius;
|
|
43
73
|
}
|
|
44
|
-
if (this.
|
|
45
|
-
|
|
74
|
+
if (this.isIncreasing) {
|
|
75
|
+
// Is largest section
|
|
76
|
+
if (this.position === this.sections - 1) {
|
|
77
|
+
return [this.borderRadius, this.borderRadius];
|
|
78
|
+
}
|
|
79
|
+
// Is smallest section and shaped like a triangle
|
|
80
|
+
if (this.position === 0 && this.pointShape === 'sharp') {
|
|
81
|
+
return [0, 0, this.borderRadius];
|
|
82
|
+
}
|
|
83
|
+
// Is smallest section
|
|
84
|
+
if (this.position === 0) {
|
|
85
|
+
return [0, 0, this.borderRadius, this.borderRadius];
|
|
86
|
+
}
|
|
46
87
|
}
|
|
47
|
-
if (this.
|
|
48
|
-
|
|
88
|
+
if (!this.isIncreasing) {
|
|
89
|
+
// Is largest section
|
|
90
|
+
if (this.position === 0) {
|
|
91
|
+
return [0, 0, this.borderRadius, this.borderRadius];
|
|
92
|
+
}
|
|
93
|
+
// Is smallest section and shaped like a triangle
|
|
94
|
+
if (this.position === this.sections - 1 && this.pointShape === 'sharp') {
|
|
95
|
+
return [this.borderRadius];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Is smallest section
|
|
99
|
+
if (this.position === this.sections - 1) {
|
|
100
|
+
return [this.borderRadius, this.borderRadius];
|
|
101
|
+
}
|
|
49
102
|
}
|
|
50
103
|
return 0;
|
|
51
104
|
}
|
|
@@ -60,23 +113,50 @@ export class Linear {
|
|
|
60
113
|
|
|
61
114
|
// Add gaps where they are needed.
|
|
62
115
|
this.points = this.points.map((point, index) => {
|
|
63
|
-
const slopeStart = this.points.at(index <= 1 ? 0 :
|
|
64
|
-
const slopeEnd = this.points.at(index <= 1 ? 1 :
|
|
116
|
+
const slopeStart = this.points.at(index <= 1 ? 0 : 3);
|
|
117
|
+
const slopeEnd = this.points.at(index <= 1 ? 1 : 2);
|
|
65
118
|
if (this.isHorizontal) {
|
|
66
|
-
const yGetter = lerpY(slopeStart.x - this.gap, slopeStart.y, slopeEnd.x
|
|
67
|
-
const xGap = point.x + (index === 0 || index === 3 ? this.gap : -this.gap);
|
|
119
|
+
const yGetter = lerpY(slopeStart.x - this.gap, slopeStart.y, slopeEnd.x, slopeEnd.y);
|
|
68
120
|
return {
|
|
69
|
-
x:
|
|
70
|
-
y: yGetter(
|
|
121
|
+
x: point.x,
|
|
122
|
+
y: yGetter(point.x)
|
|
71
123
|
};
|
|
72
124
|
}
|
|
73
|
-
const xGetter = lerpX(slopeStart.x, slopeStart.y - this.gap, slopeEnd.x, slopeEnd.y
|
|
74
|
-
const yGap = point.y + (index === 0 || index === 3 ? this.gap : -this.gap);
|
|
125
|
+
const xGetter = lerpX(slopeStart.x, slopeStart.y - this.gap, slopeEnd.x, slopeEnd.y);
|
|
75
126
|
return {
|
|
76
|
-
x: xGetter(
|
|
77
|
-
y:
|
|
127
|
+
x: xGetter(point.y),
|
|
128
|
+
y: point.y
|
|
78
129
|
};
|
|
79
130
|
});
|
|
131
|
+
if (this.pointShape === 'sharp') {
|
|
132
|
+
// In the last section, to form a triangle we need 3 points instead of 4
|
|
133
|
+
// Else the algorithm will break.
|
|
134
|
+
const isLastSection = this.position === this.sections - 1;
|
|
135
|
+
const isFirstSection = this.position === 0;
|
|
136
|
+
let firstPoint = null;
|
|
137
|
+
let secondPoint = null;
|
|
138
|
+
if (isFirstSection && this.isIncreasing) {
|
|
139
|
+
firstPoint = this.points[1];
|
|
140
|
+
secondPoint = this.points[2];
|
|
141
|
+
}
|
|
142
|
+
if (isLastSection && !this.isIncreasing) {
|
|
143
|
+
firstPoint = this.points[3];
|
|
144
|
+
secondPoint = this.points[0];
|
|
145
|
+
}
|
|
146
|
+
if (firstPoint && secondPoint) {
|
|
147
|
+
this.points = [
|
|
148
|
+
// Sharp point at the start
|
|
149
|
+
this.isHorizontal ? {
|
|
150
|
+
x: this.max.x,
|
|
151
|
+
y: (this.max.y + this.min.y) / 2
|
|
152
|
+
} : {
|
|
153
|
+
x: (this.max.x + this.min.x) / 2,
|
|
154
|
+
y: this.max.y
|
|
155
|
+
},
|
|
156
|
+
// Then other points
|
|
157
|
+
firstPoint, secondPoint];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
80
160
|
borderRadiusPolygon(this.context, this.points, this.getBorderRadius());
|
|
81
161
|
}
|
|
82
162
|
}
|