@mui/x-charts-pro 9.2.0 → 9.4.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/BarChartPro/BarChartPro.js +62 -32
- package/BarChartPro/BarChartPro.mjs +62 -32
- package/CHANGELOG.md +314 -0
- package/ChartsDataProviderPro/ChartsDataProviderPro.js +2 -2
- package/ChartsDataProviderPro/ChartsDataProviderPro.mjs +2 -2
- package/ChartsToolbarPro/ChartsToolbarImageExportTrigger.js +1 -0
- package/ChartsToolbarPro/ChartsToolbarImageExportTrigger.mjs +1 -0
- package/ChartsToolbarPro/ChartsToolbarPro.d.mts +1 -1
- package/ChartsToolbarPro/ChartsToolbarPro.d.ts +1 -1
- package/ChartsToolbarPro/ChartsToolbarRangeButtonTrigger.d.mts +1 -1
- package/ChartsToolbarPro/ChartsToolbarRangeButtonTrigger.d.ts +1 -1
- package/ChartsToolbarPro/ChartsToolbarRangeButtonTrigger.js +35 -38
- package/ChartsToolbarPro/ChartsToolbarRangeButtonTrigger.mjs +37 -40
- package/ChartsToolbarPro/Toolbar.types.d.mts +3 -2
- package/ChartsToolbarPro/Toolbar.types.d.ts +3 -2
- package/ChartsToolbarPro/rangeButtonValueToZoom.d.mts +18 -2
- package/ChartsToolbarPro/rangeButtonValueToZoom.d.ts +18 -2
- package/ChartsToolbarPro/rangeButtonValueToZoom.js +73 -10
- package/ChartsToolbarPro/rangeButtonValueToZoom.mjs +72 -10
- package/ChartsZoomSlider/internals/chartsAxisZoomSliderThumbClasses.js +9 -2
- package/ChartsZoomSlider/internals/chartsAxisZoomSliderThumbClasses.mjs +9 -2
- package/ChartsZoomSlider/internals/previews/ScatterPreviewPlot.js +2 -1
- package/ChartsZoomSlider/internals/previews/ScatterPreviewPlot.mjs +2 -1
- package/FunnelChart/FunnelChart.js +15 -15
- package/FunnelChart/FunnelChart.mjs +15 -15
- package/FunnelChart/funnelPlotSlots.types.d.mts +5 -4
- package/FunnelChart/funnelPlotSlots.types.d.ts +5 -4
- package/Heatmap/Heatmap.d.mts +3 -2
- package/Heatmap/Heatmap.d.ts +3 -2
- package/Heatmap/Heatmap.js +52 -22
- package/Heatmap/Heatmap.mjs +52 -22
- package/Heatmap/HeatmapItem.d.mts +3 -2
- package/Heatmap/HeatmapItem.d.ts +3 -2
- package/Heatmap/HeatmapItem.js +2 -0
- package/Heatmap/HeatmapItem.mjs +2 -0
- package/Heatmap/HeatmapTooltip/HeatmapTooltip.types.d.mts +3 -2
- package/Heatmap/HeatmapTooltip/HeatmapTooltip.types.d.ts +3 -2
- package/LineChartPro/LineChartPro.js +58 -28
- package/LineChartPro/LineChartPro.mjs +58 -28
- package/PieChartPro/PieChartPro.js +6 -6
- package/PieChartPro/PieChartPro.mjs +6 -6
- package/RadarChartPro/RadarChartPro.js +8 -8
- package/RadarChartPro/RadarChartPro.mjs +8 -8
- package/SankeyChart/SankeyChart.js +16 -16
- package/SankeyChart/SankeyChart.mjs +16 -16
- package/ScatterChartPro/ScatterChartPro.d.mts +2 -1
- package/ScatterChartPro/ScatterChartPro.d.ts +2 -1
- package/ScatterChartPro/ScatterChartPro.js +58 -28
- package/ScatterChartPro/ScatterChartPro.mjs +58 -28
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internals/plugins/useChartProExport/exportImage.js +8 -2
- package/internals/plugins/useChartProExport/exportImage.mjs +8 -2
- package/internals/plugins/useChartProExport/print.js +1 -0
- package/internals/plugins/useChartProExport/print.mjs +1 -0
- package/internals/plugins/useChartProExport/useChartProExport.types.d.mts +6 -0
- package/internals/plugins/useChartProExport/useChartProExport.types.d.ts +6 -0
- package/internals/plugins/useChartProZoom/useChartProZoom.js +77 -14
- package/internals/plugins/useChartProZoom/useChartProZoom.mjs +79 -15
- package/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.mts +0 -3
- package/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +0 -3
- package/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +1 -2
- package/internals/plugins/useChartProZoom/useChartProZoom.selectors.mjs +0 -1
- package/internals/plugins/useChartProZoom/useChartProZoom.types.d.mts +28 -11
- package/internals/plugins/useChartProZoom/useChartProZoom.types.d.ts +28 -11
- package/internals/slots/chartsBaseSlots.d.mts +6 -5
- package/internals/slots/chartsBaseSlots.d.ts +6 -5
- package/internals/slots/chartsIconSlots.d.mts +4 -3
- package/internals/slots/chartsIconSlots.d.ts +4 -3
- package/models/chartsSlotsComponentsPropsPro.d.mts +11 -0
- package/models/chartsSlotsComponentsPropsPro.d.ts +11 -0
- package/models/chartsSlotsComponentsPropsPro.js +5 -0
- package/models/chartsSlotsComponentsPropsPro.mjs +1 -0
- package/models/index.d.mts +1 -0
- package/models/index.d.ts +1 -0
- package/models/index.js +12 -0
- package/models/index.mjs +1 -0
- package/package.json +6 -6
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type * as React from 'react';
|
|
2
|
+
import type { ToolbarPropsOverrides } from '@mui/x-charts/models';
|
|
2
3
|
import { type ChartsToolbarProProps } from "./ChartsToolbarPro.js";
|
|
3
4
|
export interface ChartsToolbarProSlots {
|
|
4
5
|
/**
|
|
5
6
|
* Custom component for the toolbar.
|
|
6
7
|
* @default ChartsToolbar
|
|
7
8
|
*/
|
|
8
|
-
toolbar?: React.ElementType<ChartsToolbarProProps>;
|
|
9
|
+
toolbar?: React.ElementType<ChartsToolbarProProps & ToolbarPropsOverrides>;
|
|
9
10
|
}
|
|
10
11
|
export interface ChartsToolbarProSlotProps {
|
|
11
12
|
/**
|
|
12
13
|
* Props for the toolbar component.
|
|
13
14
|
*/
|
|
14
|
-
toolbar?: Partial<ChartsToolbarProProps
|
|
15
|
+
toolbar?: Partial<ChartsToolbarProProps> & ToolbarPropsOverrides;
|
|
15
16
|
}
|
|
@@ -31,6 +31,8 @@ export interface RangeButtonFunctionParams {
|
|
|
31
31
|
* @example { unit: 'year' } // Last year (step defaults to 1)
|
|
32
32
|
* - `[start, end]` — An absolute date range.
|
|
33
33
|
* @example [new Date(2024, 0, 1), new Date(2024, 6, 1)] // Jan–Jul 2024
|
|
34
|
+
* - `[start, end]` of strings — A range between two axis values, for ordinal (band/point) axes.
|
|
35
|
+
* @example ['Feb', 'May'] // From the 'Feb' category to the 'May' category
|
|
34
36
|
* - `(params) => { start, end }` — A function that receives axis context (`scaleType`, `data`, `domain`) and returns zoom percentages (0-100).
|
|
35
37
|
* @example ({ domain }) => ({ start: 0, end: 50 }) // First half of data
|
|
36
38
|
* @example ({ data }) => {
|
|
@@ -43,7 +45,7 @@ export interface RangeButtonFunctionParams {
|
|
|
43
45
|
export type RangeButtonValue = {
|
|
44
46
|
unit: RangeButtonIntervalUnit;
|
|
45
47
|
step?: number;
|
|
46
|
-
} | [Date, Date] | ((params: RangeButtonFunctionParams) => {
|
|
48
|
+
} | [Date, Date] | [string, string] | ((params: RangeButtonFunctionParams) => {
|
|
47
49
|
start: number;
|
|
48
50
|
end: number;
|
|
49
51
|
}) | null;
|
|
@@ -63,4 +65,18 @@ export type RangeButtonValue = {
|
|
|
63
65
|
export declare function rangeButtonValueToZoom(value: RangeButtonValue, params: RangeButtonFunctionParams): {
|
|
64
66
|
start: number;
|
|
65
67
|
end: number;
|
|
66
|
-
};
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Builds the {@link RangeButtonFunctionParams} for an axis from its computed domain.
|
|
71
|
+
*
|
|
72
|
+
* For ordinal (band/point) axes the domain is index-based; for continuous axes it
|
|
73
|
+
* uses the first and last domain values.
|
|
74
|
+
*
|
|
75
|
+
* @param axis The axis scale type and data.
|
|
76
|
+
* @param domain The computed domain values of the axis.
|
|
77
|
+
* @returns The params to pass to {@link rangeButtonValueToZoom}, or `undefined` if the domain is too small to zoom.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getRangeButtonDomainParams(axis: {
|
|
80
|
+
scaleType?: string;
|
|
81
|
+
data?: readonly unknown[];
|
|
82
|
+
}, domain: readonly unknown[] | undefined): RangeButtonFunctionParams | undefined;
|
|
@@ -31,6 +31,8 @@ export interface RangeButtonFunctionParams {
|
|
|
31
31
|
* @example { unit: 'year' } // Last year (step defaults to 1)
|
|
32
32
|
* - `[start, end]` — An absolute date range.
|
|
33
33
|
* @example [new Date(2024, 0, 1), new Date(2024, 6, 1)] // Jan–Jul 2024
|
|
34
|
+
* - `[start, end]` of strings — A range between two axis values, for ordinal (band/point) axes.
|
|
35
|
+
* @example ['Feb', 'May'] // From the 'Feb' category to the 'May' category
|
|
34
36
|
* - `(params) => { start, end }` — A function that receives axis context (`scaleType`, `data`, `domain`) and returns zoom percentages (0-100).
|
|
35
37
|
* @example ({ domain }) => ({ start: 0, end: 50 }) // First half of data
|
|
36
38
|
* @example ({ data }) => {
|
|
@@ -43,7 +45,7 @@ export interface RangeButtonFunctionParams {
|
|
|
43
45
|
export type RangeButtonValue = {
|
|
44
46
|
unit: RangeButtonIntervalUnit;
|
|
45
47
|
step?: number;
|
|
46
|
-
} | [Date, Date] | ((params: RangeButtonFunctionParams) => {
|
|
48
|
+
} | [Date, Date] | [string, string] | ((params: RangeButtonFunctionParams) => {
|
|
47
49
|
start: number;
|
|
48
50
|
end: number;
|
|
49
51
|
}) | null;
|
|
@@ -63,4 +65,18 @@ export type RangeButtonValue = {
|
|
|
63
65
|
export declare function rangeButtonValueToZoom(value: RangeButtonValue, params: RangeButtonFunctionParams): {
|
|
64
66
|
start: number;
|
|
65
67
|
end: number;
|
|
66
|
-
};
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Builds the {@link RangeButtonFunctionParams} for an axis from its computed domain.
|
|
71
|
+
*
|
|
72
|
+
* For ordinal (band/point) axes the domain is index-based; for continuous axes it
|
|
73
|
+
* uses the first and last domain values.
|
|
74
|
+
*
|
|
75
|
+
* @param axis The axis scale type and data.
|
|
76
|
+
* @param domain The computed domain values of the axis.
|
|
77
|
+
* @returns The params to pass to {@link rangeButtonValueToZoom}, or `undefined` if the domain is too small to zoom.
|
|
78
|
+
*/
|
|
79
|
+
export declare function getRangeButtonDomainParams(axis: {
|
|
80
|
+
scaleType?: string;
|
|
81
|
+
data?: readonly unknown[];
|
|
82
|
+
}, domain: readonly unknown[] | undefined): RangeButtonFunctionParams | undefined;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.getRangeButtonDomainParams = getRangeButtonDomainParams;
|
|
6
7
|
exports.rangeButtonValueToZoom = rangeButtonValueToZoom;
|
|
7
8
|
var _warning = require("@mui/x-internals/warning");
|
|
8
9
|
/**
|
|
@@ -21,6 +22,8 @@ var _warning = require("@mui/x-internals/warning");
|
|
|
21
22
|
* @example { unit: 'year' } // Last year (step defaults to 1)
|
|
22
23
|
* - `[start, end]` — An absolute date range.
|
|
23
24
|
* @example [new Date(2024, 0, 1), new Date(2024, 6, 1)] // Jan–Jul 2024
|
|
25
|
+
* - `[start, end]` of strings — A range between two axis values, for ordinal (band/point) axes.
|
|
26
|
+
* @example ['Feb', 'May'] // From the 'Feb' category to the 'May' category
|
|
24
27
|
* - `(params) => { start, end }` — A function that receives axis context (`scaleType`, `data`, `domain`) and returns zoom percentages (0-100).
|
|
25
28
|
* @example ({ domain }) => ({ start: 0, end: 50 }) // First half of data
|
|
26
29
|
* @example ({ data }) => {
|
|
@@ -104,6 +107,7 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
104
107
|
};
|
|
105
108
|
}
|
|
106
109
|
const {
|
|
110
|
+
scaleType,
|
|
107
111
|
domain: {
|
|
108
112
|
min: domainMin,
|
|
109
113
|
max: domainMax
|
|
@@ -111,13 +115,42 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
111
115
|
data: ordinalData
|
|
112
116
|
} = params;
|
|
113
117
|
|
|
118
|
+
// Ordinal axis range — resolve each endpoint to its matching value on the axis.
|
|
119
|
+
// Band/point axes can carry strings, numbers, or dates, so the match is by strict equality.
|
|
120
|
+
if (Array.isArray(value) && ordinalData) {
|
|
121
|
+
const startIndex = ordinalData.findIndex(item => item === value[0]);
|
|
122
|
+
const endIndex = ordinalData.findIndex(item => item === value[1]);
|
|
123
|
+
if (startIndex !== -1 && endIndex !== -1) {
|
|
124
|
+
if (process.env.NODE_ENV !== 'production' && endIndex < startIndex) {
|
|
125
|
+
(0, _warning.warnOnce)(['MUI X Charts: Range button received a range whose end value comes before its start value.', 'This produces an empty zoom range.']);
|
|
126
|
+
}
|
|
127
|
+
// Band items span [i/L, (i+1)/L] along the axis; point items sit at i/(L-1).
|
|
128
|
+
// For band, the end index is inclusive, so the right edge of the band is `(endIndex + 1) / L`.
|
|
129
|
+
if (scaleType === 'band') {
|
|
130
|
+
return {
|
|
131
|
+
start: startIndex / ordinalData.length * 100,
|
|
132
|
+
end: (endIndex + 1) / ordinalData.length * 100
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
const maxIndex = ordinalData.length - 1;
|
|
136
|
+
return {
|
|
137
|
+
start: maxIndex === 0 ? 0 : startIndex / maxIndex * 100,
|
|
138
|
+
end: maxIndex === 0 ? 100 : endIndex / maxIndex * 100
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// No match on the axis values — fall through in case they are date-like.
|
|
142
|
+
}
|
|
143
|
+
|
|
114
144
|
// For ordinal axes with date-like data, resolve date ranges and intervals to matching indices.
|
|
115
145
|
const timestamps = ordinalData ? toTimestampArray(ordinalData) : undefined;
|
|
116
146
|
if (timestamps) {
|
|
147
|
+
const isBand = scaleType === 'band';
|
|
148
|
+
const denominator = isBand ? timestamps.length : timestamps.length - 1;
|
|
117
149
|
const maxIndex = timestamps.length - 1;
|
|
150
|
+
const toPercent = (i, defaultPercent) => denominator === 0 ? defaultPercent : i / denominator * 100;
|
|
118
151
|
if (Array.isArray(value)) {
|
|
119
|
-
const startTarget = value[0].
|
|
120
|
-
const endTarget = value[1].
|
|
152
|
+
const startTarget = toTimestamp(value[0]) ?? Number.NaN;
|
|
153
|
+
const endTarget = toTimestamp(value[1]) ?? Number.NaN;
|
|
121
154
|
if (process.env.NODE_ENV !== 'production' && endTarget < startTarget) {
|
|
122
155
|
(0, _warning.warnOnce)(['MUI X Charts: Range button received a date range whose end is before its start.', 'This produces an empty zoom range.']);
|
|
123
156
|
}
|
|
@@ -126,8 +159,8 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
126
159
|
const startIndex = firstGte === -1 ? maxIndex : firstGte;
|
|
127
160
|
const endIndex = lastLte === -1 ? 0 : lastLte;
|
|
128
161
|
return {
|
|
129
|
-
start: startIndex
|
|
130
|
-
end: endIndex
|
|
162
|
+
start: toPercent(startIndex, 0),
|
|
163
|
+
end: toPercent(endIndex + (isBand ? 1 : 0), 100)
|
|
131
164
|
};
|
|
132
165
|
}
|
|
133
166
|
|
|
@@ -138,12 +171,12 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
138
171
|
const firstGte = timestamps.findIndex(ts => !Number.isNaN(ts) && ts >= targetStartMs);
|
|
139
172
|
const startIndex = firstGte === -1 ? maxIndex : firstGte;
|
|
140
173
|
return {
|
|
141
|
-
start: startIndex
|
|
174
|
+
start: toPercent(startIndex, 0),
|
|
142
175
|
end: 100
|
|
143
176
|
};
|
|
144
177
|
}
|
|
145
178
|
if (process.env.NODE_ENV !== 'production' && ordinalData !== undefined) {
|
|
146
|
-
(0, _warning.warnOnce)(['MUI X Charts: Range button received a
|
|
179
|
+
(0, _warning.warnOnce)(['MUI X Charts: Range button received a value for an ordinal axis whose data could not be matched.', 'The zoom range may not match the intended selection. Provide axis values that exist on the axis, date-like axis data, or use a function value.']);
|
|
147
180
|
}
|
|
148
181
|
const domainRange = domainMax - domainMin;
|
|
149
182
|
if (domainRange <= 0) {
|
|
@@ -155,12 +188,13 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
155
188
|
|
|
156
189
|
// Absolute date range
|
|
157
190
|
if (Array.isArray(value)) {
|
|
158
|
-
const
|
|
159
|
-
|
|
191
|
+
const rangeStart = toTimestamp(value[0]) ?? domainMin;
|
|
192
|
+
const rangeEnd = toTimestamp(value[1]) ?? domainMax;
|
|
193
|
+
if (process.env.NODE_ENV !== 'production' && rangeEnd < rangeStart) {
|
|
160
194
|
(0, _warning.warnOnce)(['MUI X Charts: Range button received a date range whose end is before its start.', 'This produces an empty zoom range.']);
|
|
161
195
|
}
|
|
162
|
-
const startPercent = (rangeStart
|
|
163
|
-
const endPercent = (rangeEnd
|
|
196
|
+
const startPercent = (rangeStart - domainMin) / domainRange * 100;
|
|
197
|
+
const endPercent = (rangeEnd - domainMin) / domainRange * 100;
|
|
164
198
|
return {
|
|
165
199
|
start: startPercent,
|
|
166
200
|
end: endPercent
|
|
@@ -176,6 +210,35 @@ function rangeButtonValueToZoom(value, params) {
|
|
|
176
210
|
};
|
|
177
211
|
}
|
|
178
212
|
|
|
213
|
+
/**
|
|
214
|
+
* Builds the {@link RangeButtonFunctionParams} for an axis from its computed domain.
|
|
215
|
+
*
|
|
216
|
+
* For ordinal (band/point) axes the domain is index-based; for continuous axes it
|
|
217
|
+
* uses the first and last domain values.
|
|
218
|
+
*
|
|
219
|
+
* @param axis The axis scale type and data.
|
|
220
|
+
* @param domain The computed domain values of the axis.
|
|
221
|
+
* @returns The params to pass to {@link rangeButtonValueToZoom}, or `undefined` if the domain is too small to zoom.
|
|
222
|
+
*/
|
|
223
|
+
function getRangeButtonDomainParams(axis, domain) {
|
|
224
|
+
if (!domain || domain.length < 2) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
const scaleType = axis.scaleType ?? 'linear';
|
|
228
|
+
const isOrdinal = scaleType === 'band' || scaleType === 'point';
|
|
229
|
+
return {
|
|
230
|
+
scaleType,
|
|
231
|
+
data: axis.data,
|
|
232
|
+
domain: isOrdinal ? {
|
|
233
|
+
min: 0,
|
|
234
|
+
max: domain.length - 1
|
|
235
|
+
} : {
|
|
236
|
+
min: Number(domain[0]),
|
|
237
|
+
max: Number(domain[domain.length - 1])
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
179
242
|
/**
|
|
180
243
|
* Computes the start timestamp for a calendar interval subtracted from a reference point.
|
|
181
244
|
*/
|
|
@@ -16,6 +16,8 @@ import { warnOnce } from '@mui/x-internals/warning';
|
|
|
16
16
|
* @example { unit: 'year' } // Last year (step defaults to 1)
|
|
17
17
|
* - `[start, end]` — An absolute date range.
|
|
18
18
|
* @example [new Date(2024, 0, 1), new Date(2024, 6, 1)] // Jan–Jul 2024
|
|
19
|
+
* - `[start, end]` of strings — A range between two axis values, for ordinal (band/point) axes.
|
|
20
|
+
* @example ['Feb', 'May'] // From the 'Feb' category to the 'May' category
|
|
19
21
|
* - `(params) => { start, end }` — A function that receives axis context (`scaleType`, `data`, `domain`) and returns zoom percentages (0-100).
|
|
20
22
|
* @example ({ domain }) => ({ start: 0, end: 50 }) // First half of data
|
|
21
23
|
* @example ({ data }) => {
|
|
@@ -99,6 +101,7 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
const {
|
|
104
|
+
scaleType,
|
|
102
105
|
domain: {
|
|
103
106
|
min: domainMin,
|
|
104
107
|
max: domainMax
|
|
@@ -106,13 +109,42 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
106
109
|
data: ordinalData
|
|
107
110
|
} = params;
|
|
108
111
|
|
|
112
|
+
// Ordinal axis range — resolve each endpoint to its matching value on the axis.
|
|
113
|
+
// Band/point axes can carry strings, numbers, or dates, so the match is by strict equality.
|
|
114
|
+
if (Array.isArray(value) && ordinalData) {
|
|
115
|
+
const startIndex = ordinalData.findIndex(item => item === value[0]);
|
|
116
|
+
const endIndex = ordinalData.findIndex(item => item === value[1]);
|
|
117
|
+
if (startIndex !== -1 && endIndex !== -1) {
|
|
118
|
+
if (process.env.NODE_ENV !== 'production' && endIndex < startIndex) {
|
|
119
|
+
warnOnce(['MUI X Charts: Range button received a range whose end value comes before its start value.', 'This produces an empty zoom range.']);
|
|
120
|
+
}
|
|
121
|
+
// Band items span [i/L, (i+1)/L] along the axis; point items sit at i/(L-1).
|
|
122
|
+
// For band, the end index is inclusive, so the right edge of the band is `(endIndex + 1) / L`.
|
|
123
|
+
if (scaleType === 'band') {
|
|
124
|
+
return {
|
|
125
|
+
start: startIndex / ordinalData.length * 100,
|
|
126
|
+
end: (endIndex + 1) / ordinalData.length * 100
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const maxIndex = ordinalData.length - 1;
|
|
130
|
+
return {
|
|
131
|
+
start: maxIndex === 0 ? 0 : startIndex / maxIndex * 100,
|
|
132
|
+
end: maxIndex === 0 ? 100 : endIndex / maxIndex * 100
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// No match on the axis values — fall through in case they are date-like.
|
|
136
|
+
}
|
|
137
|
+
|
|
109
138
|
// For ordinal axes with date-like data, resolve date ranges and intervals to matching indices.
|
|
110
139
|
const timestamps = ordinalData ? toTimestampArray(ordinalData) : undefined;
|
|
111
140
|
if (timestamps) {
|
|
141
|
+
const isBand = scaleType === 'band';
|
|
142
|
+
const denominator = isBand ? timestamps.length : timestamps.length - 1;
|
|
112
143
|
const maxIndex = timestamps.length - 1;
|
|
144
|
+
const toPercent = (i, defaultPercent) => denominator === 0 ? defaultPercent : i / denominator * 100;
|
|
113
145
|
if (Array.isArray(value)) {
|
|
114
|
-
const startTarget = value[0].
|
|
115
|
-
const endTarget = value[1].
|
|
146
|
+
const startTarget = toTimestamp(value[0]) ?? Number.NaN;
|
|
147
|
+
const endTarget = toTimestamp(value[1]) ?? Number.NaN;
|
|
116
148
|
if (process.env.NODE_ENV !== 'production' && endTarget < startTarget) {
|
|
117
149
|
warnOnce(['MUI X Charts: Range button received a date range whose end is before its start.', 'This produces an empty zoom range.']);
|
|
118
150
|
}
|
|
@@ -121,8 +153,8 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
121
153
|
const startIndex = firstGte === -1 ? maxIndex : firstGte;
|
|
122
154
|
const endIndex = lastLte === -1 ? 0 : lastLte;
|
|
123
155
|
return {
|
|
124
|
-
start: startIndex
|
|
125
|
-
end: endIndex
|
|
156
|
+
start: toPercent(startIndex, 0),
|
|
157
|
+
end: toPercent(endIndex + (isBand ? 1 : 0), 100)
|
|
126
158
|
};
|
|
127
159
|
}
|
|
128
160
|
|
|
@@ -133,12 +165,12 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
133
165
|
const firstGte = timestamps.findIndex(ts => !Number.isNaN(ts) && ts >= targetStartMs);
|
|
134
166
|
const startIndex = firstGte === -1 ? maxIndex : firstGte;
|
|
135
167
|
return {
|
|
136
|
-
start: startIndex
|
|
168
|
+
start: toPercent(startIndex, 0),
|
|
137
169
|
end: 100
|
|
138
170
|
};
|
|
139
171
|
}
|
|
140
172
|
if (process.env.NODE_ENV !== 'production' && ordinalData !== undefined) {
|
|
141
|
-
warnOnce(['MUI X Charts: Range button received a
|
|
173
|
+
warnOnce(['MUI X Charts: Range button received a value for an ordinal axis whose data could not be matched.', 'The zoom range may not match the intended selection. Provide axis values that exist on the axis, date-like axis data, or use a function value.']);
|
|
142
174
|
}
|
|
143
175
|
const domainRange = domainMax - domainMin;
|
|
144
176
|
if (domainRange <= 0) {
|
|
@@ -150,12 +182,13 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
150
182
|
|
|
151
183
|
// Absolute date range
|
|
152
184
|
if (Array.isArray(value)) {
|
|
153
|
-
const
|
|
154
|
-
|
|
185
|
+
const rangeStart = toTimestamp(value[0]) ?? domainMin;
|
|
186
|
+
const rangeEnd = toTimestamp(value[1]) ?? domainMax;
|
|
187
|
+
if (process.env.NODE_ENV !== 'production' && rangeEnd < rangeStart) {
|
|
155
188
|
warnOnce(['MUI X Charts: Range button received a date range whose end is before its start.', 'This produces an empty zoom range.']);
|
|
156
189
|
}
|
|
157
|
-
const startPercent = (rangeStart
|
|
158
|
-
const endPercent = (rangeEnd
|
|
190
|
+
const startPercent = (rangeStart - domainMin) / domainRange * 100;
|
|
191
|
+
const endPercent = (rangeEnd - domainMin) / domainRange * 100;
|
|
159
192
|
return {
|
|
160
193
|
start: startPercent,
|
|
161
194
|
end: endPercent
|
|
@@ -171,6 +204,35 @@ export function rangeButtonValueToZoom(value, params) {
|
|
|
171
204
|
};
|
|
172
205
|
}
|
|
173
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Builds the {@link RangeButtonFunctionParams} for an axis from its computed domain.
|
|
209
|
+
*
|
|
210
|
+
* For ordinal (band/point) axes the domain is index-based; for continuous axes it
|
|
211
|
+
* uses the first and last domain values.
|
|
212
|
+
*
|
|
213
|
+
* @param axis The axis scale type and data.
|
|
214
|
+
* @param domain The computed domain values of the axis.
|
|
215
|
+
* @returns The params to pass to {@link rangeButtonValueToZoom}, or `undefined` if the domain is too small to zoom.
|
|
216
|
+
*/
|
|
217
|
+
export function getRangeButtonDomainParams(axis, domain) {
|
|
218
|
+
if (!domain || domain.length < 2) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
const scaleType = axis.scaleType ?? 'linear';
|
|
222
|
+
const isOrdinal = scaleType === 'band' || scaleType === 'point';
|
|
223
|
+
return {
|
|
224
|
+
scaleType,
|
|
225
|
+
data: axis.data,
|
|
226
|
+
domain: isOrdinal ? {
|
|
227
|
+
min: 0,
|
|
228
|
+
max: domain.length - 1
|
|
229
|
+
} : {
|
|
230
|
+
min: Number(domain[0]),
|
|
231
|
+
max: Number(domain[domain.length - 1])
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
174
236
|
/**
|
|
175
237
|
* Computes the start timestamp for a calendar interval subtracted from a reference point.
|
|
176
238
|
*/
|
|
@@ -10,9 +10,16 @@ exports.useUtilityClasses = void 0;
|
|
|
10
10
|
var _generateUtilityClasses = _interopRequireDefault(require("@mui/utils/generateUtilityClasses"));
|
|
11
11
|
var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
|
|
12
12
|
var _generateUtilityClass = _interopRequireDefault(require("@mui/utils/generateUtilityClass"));
|
|
13
|
-
const
|
|
13
|
+
const CORRECT_PREFIX = 'MuiChartsAxisZoomSliderThumb';
|
|
14
|
+
// TODO v10: remove `MuiChartAxisZoomSliderThumb`. Kept for backwards compatibility with
|
|
15
|
+
// users targeting the historically-incorrect prefix (missing the `s` in `Charts`).
|
|
16
|
+
const LEGACY_PREFIX = 'MuiChartAxisZoomSliderThumb';
|
|
17
|
+
const chartsAxisZoomSliderThumbClasses = exports.chartsAxisZoomSliderThumbClasses = (0, _generateUtilityClasses.default)(CORRECT_PREFIX, ['root', 'horizontal', 'vertical', 'start', 'end']);
|
|
18
|
+
|
|
19
|
+
// Returns both the correct and legacy class names so existing CSS targeting the legacy
|
|
20
|
+
// prefix continues to work.
|
|
14
21
|
function getAxisZoomSliderThumbUtilityClass(slot) {
|
|
15
|
-
return (0, _generateUtilityClass.default)(
|
|
22
|
+
return `${(0, _generateUtilityClass.default)(CORRECT_PREFIX, slot)} ${(0, _generateUtilityClass.default)(LEGACY_PREFIX, slot)}`;
|
|
16
23
|
}
|
|
17
24
|
const useUtilityClasses = ownerState => {
|
|
18
25
|
const {
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
|
|
2
2
|
import composeClasses from '@mui/utils/composeClasses';
|
|
3
3
|
import generateUtilityClass from '@mui/utils/generateUtilityClass';
|
|
4
|
-
|
|
4
|
+
const CORRECT_PREFIX = 'MuiChartsAxisZoomSliderThumb';
|
|
5
|
+
// TODO v10: remove `MuiChartAxisZoomSliderThumb`. Kept for backwards compatibility with
|
|
6
|
+
// users targeting the historically-incorrect prefix (missing the `s` in `Charts`).
|
|
7
|
+
const LEGACY_PREFIX = 'MuiChartAxisZoomSliderThumb';
|
|
8
|
+
export const chartsAxisZoomSliderThumbClasses = generateUtilityClasses(CORRECT_PREFIX, ['root', 'horizontal', 'vertical', 'start', 'end']);
|
|
9
|
+
|
|
10
|
+
// Returns both the correct and legacy class names so existing CSS targeting the legacy
|
|
11
|
+
// prefix continues to work.
|
|
5
12
|
export function getAxisZoomSliderThumbUtilityClass(slot) {
|
|
6
|
-
return generateUtilityClass(
|
|
13
|
+
return `${generateUtilityClass(CORRECT_PREFIX, slot)} ${generateUtilityClass(LEGACY_PREFIX, slot)}`;
|
|
7
14
|
}
|
|
8
15
|
export const useUtilityClasses = ownerState => {
|
|
9
16
|
const {
|
|
@@ -47,6 +47,7 @@ function ScatterPreviewPlot({
|
|
|
47
47
|
id,
|
|
48
48
|
xAxisId,
|
|
49
49
|
yAxisId,
|
|
50
|
+
colorAxisId,
|
|
50
51
|
zAxisId,
|
|
51
52
|
color
|
|
52
53
|
} = series[seriesId];
|
|
@@ -57,7 +58,7 @@ function ScatterPreviewPlot({
|
|
|
57
58
|
if (xAxis?.id !== axisId && yAxis?.id !== axisId) {
|
|
58
59
|
return null;
|
|
59
60
|
}
|
|
60
|
-
const colorGetter = _internals.scatterSeriesConfig.colorProcessor(series[seriesId], xAxis, yAxis, zAxes[zAxisId ?? defaultZAxisId]);
|
|
61
|
+
const colorGetter = _internals.scatterSeriesConfig.colorProcessor(series[seriesId], xAxis, yAxis, zAxes[colorAxisId ?? zAxisId ?? defaultZAxisId]);
|
|
61
62
|
const xScale = xAxis.scale;
|
|
62
63
|
const yScale = yAxis.scale;
|
|
63
64
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ScatterPreviewItems, {
|
|
@@ -40,6 +40,7 @@ export function ScatterPreviewPlot({
|
|
|
40
40
|
id,
|
|
41
41
|
xAxisId,
|
|
42
42
|
yAxisId,
|
|
43
|
+
colorAxisId,
|
|
43
44
|
zAxisId,
|
|
44
45
|
color
|
|
45
46
|
} = series[seriesId];
|
|
@@ -50,7 +51,7 @@ export function ScatterPreviewPlot({
|
|
|
50
51
|
if (xAxis?.id !== axisId && yAxis?.id !== axisId) {
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
|
-
const colorGetter = scatterSeriesConfig.colorProcessor(series[seriesId], xAxis, yAxis, zAxes[zAxisId ?? defaultZAxisId]);
|
|
54
|
+
const colorGetter = scatterSeriesConfig.colorProcessor(series[seriesId], xAxis, yAxis, zAxes[colorAxisId ?? zAxisId ?? defaultZAxisId]);
|
|
54
55
|
const xScale = xAxis.scale;
|
|
55
56
|
const yScale = yAxis.scale;
|
|
56
57
|
return /*#__PURE__*/_jsx(ScatterPreviewItems, {
|
|
@@ -106,7 +106,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
106
106
|
disableTicks: _propTypes.default.bool,
|
|
107
107
|
id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
|
|
108
108
|
position: _propTypes.default.oneOf(['bottom', 'left', 'none', 'right', 'top']),
|
|
109
|
-
scaleType: _propTypes.default.oneOf(['
|
|
109
|
+
scaleType: _propTypes.default.oneOf(['linear']),
|
|
110
110
|
size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]),
|
|
111
111
|
tickLabelStyle: _propTypes.default.object,
|
|
112
112
|
tickSize: _propTypes.default.number
|
|
@@ -116,7 +116,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
116
116
|
disableTicks: _propTypes.default.bool,
|
|
117
117
|
id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
|
|
118
118
|
position: _propTypes.default.oneOf(['bottom', 'left', 'none', 'right', 'top']),
|
|
119
|
-
scaleType: _propTypes.default.oneOf(['
|
|
119
|
+
scaleType: _propTypes.default.oneOf(['log']),
|
|
120
120
|
size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]),
|
|
121
121
|
tickLabelStyle: _propTypes.default.object,
|
|
122
122
|
tickSize: _propTypes.default.number
|
|
@@ -146,7 +146,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
146
146
|
disableTicks: _propTypes.default.bool,
|
|
147
147
|
id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
|
|
148
148
|
position: _propTypes.default.oneOf(['bottom', 'left', 'none', 'right', 'top']),
|
|
149
|
-
scaleType: _propTypes.default.oneOf(['
|
|
149
|
+
scaleType: _propTypes.default.oneOf(['symlog']),
|
|
150
150
|
size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]),
|
|
151
151
|
tickLabelStyle: _propTypes.default.object,
|
|
152
152
|
tickSize: _propTypes.default.number
|
|
@@ -156,7 +156,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
156
156
|
disableTicks: _propTypes.default.bool,
|
|
157
157
|
id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
|
|
158
158
|
position: _propTypes.default.oneOf(['bottom', 'left', 'none', 'right', 'top']),
|
|
159
|
-
scaleType: _propTypes.default.oneOf(['
|
|
159
|
+
scaleType: _propTypes.default.oneOf(['time']),
|
|
160
160
|
size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]),
|
|
161
161
|
tickLabelStyle: _propTypes.default.object,
|
|
162
162
|
tickSize: _propTypes.default.number
|
|
@@ -166,7 +166,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
166
166
|
disableTicks: _propTypes.default.bool,
|
|
167
167
|
id: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
|
|
168
168
|
position: _propTypes.default.oneOf(['bottom', 'left', 'none', 'right', 'top']),
|
|
169
|
-
scaleType: _propTypes.default.oneOf(['
|
|
169
|
+
scaleType: _propTypes.default.oneOf(['utc']),
|
|
170
170
|
size: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]),
|
|
171
171
|
tickLabelStyle: _propTypes.default.object,
|
|
172
172
|
tickSize: _propTypes.default.number
|
|
@@ -228,11 +228,11 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
228
228
|
hiddenItems: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.shape({
|
|
229
229
|
dataIndex: _propTypes.default.number,
|
|
230
230
|
seriesId: _propTypes.default.string.isRequired,
|
|
231
|
-
type: _propTypes.default.oneOf(['funnel'])
|
|
231
|
+
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
232
232
|
}), _propTypes.default.shape({
|
|
233
233
|
dataIndex: _propTypes.default.number,
|
|
234
234
|
seriesId: _propTypes.default.string.isRequired,
|
|
235
|
-
type: _propTypes.default.oneOf(['funnel'])
|
|
235
|
+
type: _propTypes.default.oneOf(['funnel'])
|
|
236
236
|
})]).isRequired),
|
|
237
237
|
/**
|
|
238
238
|
* If `true`, the legend is not rendered.
|
|
@@ -245,11 +245,11 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
245
245
|
*/
|
|
246
246
|
highlightedItem: _propTypes.default.oneOfType([_propTypes.default.shape({
|
|
247
247
|
dataIndex: _propTypes.default.number,
|
|
248
|
-
seriesId: _propTypes.default.string.isRequired
|
|
249
|
-
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
248
|
+
seriesId: _propTypes.default.string.isRequired
|
|
250
249
|
}), _propTypes.default.shape({
|
|
251
250
|
dataIndex: _propTypes.default.number,
|
|
252
|
-
seriesId: _propTypes.default.string.isRequired
|
|
251
|
+
seriesId: _propTypes.default.string.isRequired,
|
|
252
|
+
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
253
253
|
})]),
|
|
254
254
|
/**
|
|
255
255
|
* This prop is used to help implement the accessibility logic.
|
|
@@ -280,11 +280,11 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
280
280
|
initialHiddenItems: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.shape({
|
|
281
281
|
dataIndex: _propTypes.default.number,
|
|
282
282
|
seriesId: _propTypes.default.string.isRequired,
|
|
283
|
-
type: _propTypes.default.oneOf(['funnel'])
|
|
283
|
+
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
284
284
|
}), _propTypes.default.shape({
|
|
285
285
|
dataIndex: _propTypes.default.number,
|
|
286
286
|
seriesId: _propTypes.default.string.isRequired,
|
|
287
|
-
type: _propTypes.default.oneOf(['funnel'])
|
|
287
|
+
type: _propTypes.default.oneOf(['funnel'])
|
|
288
288
|
})]).isRequired),
|
|
289
289
|
/**
|
|
290
290
|
* If `true`, a loading overlay is displayed.
|
|
@@ -370,11 +370,11 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
|
|
|
370
370
|
*/
|
|
371
371
|
tooltipItem: _propTypes.default.oneOfType([_propTypes.default.shape({
|
|
372
372
|
dataIndex: _propTypes.default.number.isRequired,
|
|
373
|
-
seriesId: _propTypes.default.string.isRequired
|
|
374
|
-
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
373
|
+
seriesId: _propTypes.default.string.isRequired
|
|
375
374
|
}), _propTypes.default.shape({
|
|
376
375
|
dataIndex: _propTypes.default.number.isRequired,
|
|
377
|
-
seriesId: _propTypes.default.string.isRequired
|
|
376
|
+
seriesId: _propTypes.default.string.isRequired,
|
|
377
|
+
type: _propTypes.default.oneOf(['funnel']).isRequired
|
|
378
378
|
})]),
|
|
379
379
|
/**
|
|
380
380
|
* The width of the chart in px. If not defined, it takes the width of the parent element.
|