@mui/x-charts 8.9.2 → 8.10.1
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 +20 -0
- package/CHANGELOG.md +217 -6
- package/ChartContainer/ChartContainer.js +30 -0
- package/ChartsAxisHighlight/ChartsAxisHighlight.js +2 -2
- package/ChartsAxisHighlight/ChartsXAxisHighlight.js +1 -3
- package/ChartsAxisHighlight/ChartsYAxisHighlight.js +1 -3
- package/ChartsLabel/labelGradientClasses.d.ts +1 -1
- package/ChartsLabel/labelMarkClasses.d.ts +1 -1
- package/ChartsReferenceLine/ChartsXReferenceLine.d.ts +1 -1
- package/ChartsReferenceLine/ChartsYReferenceLine.d.ts +1 -1
- package/ChartsTooltip/ChartsTooltip.d.ts +2 -1
- package/ChartsTooltip/ChartsTooltip.js +3 -3
- package/ChartsTooltip/ChartsTooltipContainer.d.ts +5 -5
- package/ChartsTooltip/ChartsTooltipContainer.js +11 -5
- package/ChartsTooltip/ChartsTooltipTable.d.ts +1 -1
- package/ChartsTooltip/ChartsTooltipTable.js +1 -0
- package/ChartsTooltip/chartsTooltipClasses.d.ts +1 -1
- package/ChartsXAxis/ChartsGroupedXAxis.d.ts +7 -0
- package/ChartsXAxis/ChartsGroupedXAxis.js +143 -0
- package/ChartsXAxis/ChartsSingleXAxis.d.ts +7 -0
- package/ChartsXAxis/ChartsSingleXAxis.js +144 -0
- package/ChartsXAxis/ChartsXAxis.d.ts +1 -1
- package/ChartsXAxis/ChartsXAxis.js +8 -210
- package/ChartsXAxis/getVisibleLabels.d.ts +2 -2
- package/ChartsXAxis/useAxisProps.d.ts +4526 -0
- package/ChartsXAxis/useAxisProps.js +105 -0
- package/ChartsXAxis/utilities.d.ts +11 -0
- package/ChartsXAxis/utilities.js +43 -0
- package/ChartsYAxis/ChartsGroupedYAxis.d.ts +7 -0
- package/ChartsYAxis/ChartsGroupedYAxis.js +144 -0
- package/ChartsYAxis/ChartsSingleYAxis.d.ts +7 -0
- package/ChartsYAxis/ChartsSingleYAxis.js +133 -0
- package/ChartsYAxis/ChartsYAxis.d.ts +1 -1
- package/ChartsYAxis/ChartsYAxis.js +12 -211
- package/ChartsYAxis/useAxisProps.d.ts +4452 -0
- package/ChartsYAxis/useAxisProps.js +115 -0
- package/ChartsYAxis/utilities.d.ts +10 -0
- package/ChartsYAxis/utilities.js +42 -0
- package/LineChart/LineChart.js +20 -0
- package/RadarChart/index.d.ts +9 -2
- package/RadarChart/index.js +13 -14
- package/ScatterChart/ScatterChart.d.ts +8 -1
- package/ScatterChart/ScatterChart.js +20 -0
- package/SparkLineChart/SparkLineChart.d.ts +15 -5
- package/SparkLineChart/SparkLineChart.js +77 -34
- package/esm/BarChart/BarChart.js +20 -0
- package/esm/ChartContainer/ChartContainer.js +30 -0
- package/esm/ChartsAxisHighlight/ChartsAxisHighlight.js +2 -2
- package/esm/ChartsAxisHighlight/ChartsXAxisHighlight.js +1 -3
- package/esm/ChartsAxisHighlight/ChartsYAxisHighlight.js +1 -3
- package/esm/ChartsLabel/labelGradientClasses.d.ts +1 -1
- package/esm/ChartsLabel/labelMarkClasses.d.ts +1 -1
- package/esm/ChartsReferenceLine/ChartsXReferenceLine.d.ts +1 -1
- package/esm/ChartsReferenceLine/ChartsYReferenceLine.d.ts +1 -1
- package/esm/ChartsTooltip/ChartsTooltip.d.ts +2 -1
- package/esm/ChartsTooltip/ChartsTooltip.js +3 -3
- package/esm/ChartsTooltip/ChartsTooltipContainer.d.ts +5 -5
- package/esm/ChartsTooltip/ChartsTooltipContainer.js +11 -5
- package/esm/ChartsTooltip/ChartsTooltipTable.d.ts +1 -1
- package/esm/ChartsTooltip/ChartsTooltipTable.js +1 -0
- package/esm/ChartsTooltip/chartsTooltipClasses.d.ts +1 -1
- package/esm/ChartsXAxis/ChartsGroupedXAxis.d.ts +7 -0
- package/esm/ChartsXAxis/ChartsGroupedXAxis.js +137 -0
- package/esm/ChartsXAxis/ChartsSingleXAxis.d.ts +7 -0
- package/esm/ChartsXAxis/ChartsSingleXAxis.js +140 -0
- package/esm/ChartsXAxis/ChartsXAxis.d.ts +1 -1
- package/esm/ChartsXAxis/ChartsXAxis.js +7 -207
- package/esm/ChartsXAxis/getVisibleLabels.d.ts +2 -2
- package/esm/ChartsXAxis/useAxisProps.d.ts +4526 -0
- package/esm/ChartsXAxis/useAxisProps.js +98 -0
- package/esm/ChartsXAxis/utilities.d.ts +11 -0
- package/esm/ChartsXAxis/utilities.js +35 -0
- package/esm/ChartsYAxis/ChartsGroupedYAxis.d.ts +7 -0
- package/esm/ChartsYAxis/ChartsGroupedYAxis.js +138 -0
- package/esm/ChartsYAxis/ChartsSingleYAxis.d.ts +7 -0
- package/esm/ChartsYAxis/ChartsSingleYAxis.js +129 -0
- package/esm/ChartsYAxis/ChartsYAxis.d.ts +1 -1
- package/esm/ChartsYAxis/ChartsYAxis.js +10 -207
- package/esm/ChartsYAxis/useAxisProps.d.ts +4452 -0
- package/esm/ChartsYAxis/useAxisProps.js +108 -0
- package/esm/ChartsYAxis/utilities.d.ts +10 -0
- package/esm/ChartsYAxis/utilities.js +34 -0
- package/esm/LineChart/LineChart.js +20 -0
- package/esm/RadarChart/index.d.ts +9 -2
- package/esm/RadarChart/index.js +12 -2
- package/esm/ScatterChart/ScatterChart.d.ts +8 -1
- package/esm/ScatterChart/ScatterChart.js +20 -0
- package/esm/SparkLineChart/SparkLineChart.d.ts +15 -5
- package/esm/SparkLineChart/SparkLineChart.js +77 -34
- package/esm/hooks/useTicksGrouped.d.ts +28 -0
- package/esm/hooks/useTicksGrouped.js +98 -0
- package/esm/index.js +1 -1
- package/esm/internals/animation/Transition.js +2 -5
- package/esm/internals/configInit.js +2 -2
- package/esm/internals/getScale.d.ts +1 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.d.ts +3 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.js +32 -23
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.d.ts +1 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisValue.d.ts +1 -1
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisValue.js +3 -4
- package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianInteraction.selectors.js +2 -2
- package/esm/internals/plugins/utils/ChartStore.js +16 -18
- package/esm/models/axis.d.ts +46 -2
- package/esm/tests/web-components.js +2 -4
- package/hooks/useTicksGrouped.d.ts +28 -0
- package/hooks/useTicksGrouped.js +104 -0
- package/index.js +1 -1
- package/internals/animation/Transition.js +2 -5
- package/internals/configInit.js +2 -2
- package/internals/getScale.d.ts +1 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.d.ts +3 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.js +34 -23
- package/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.d.ts +1 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisValue.d.ts +1 -1
- package/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisValue.js +3 -4
- package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianInteraction.selectors.js +2 -2
- package/internals/plugins/utils/ChartStore.js +16 -18
- package/models/axis.d.ts +46 -2
- package/package.json +16 -18
- package/tests/web-components.js +2 -4
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { isBandScale } from "../internals/isBandScale.js";
|
|
5
|
+
const offsetRatio = {
|
|
6
|
+
start: 0,
|
|
7
|
+
extremities: 0,
|
|
8
|
+
end: 1,
|
|
9
|
+
middle: 0.5,
|
|
10
|
+
tick: 0
|
|
11
|
+
};
|
|
12
|
+
export function useTicksGrouped(options) {
|
|
13
|
+
const {
|
|
14
|
+
scale,
|
|
15
|
+
tickInterval,
|
|
16
|
+
tickLabelPlacement = 'middle',
|
|
17
|
+
tickPlacement = 'extremities',
|
|
18
|
+
groups
|
|
19
|
+
} = options;
|
|
20
|
+
return React.useMemo(() => {
|
|
21
|
+
const domain = scale.domain();
|
|
22
|
+
const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain;
|
|
23
|
+
if (scale.bandwidth() > 0) {
|
|
24
|
+
// scale type = 'band'
|
|
25
|
+
const entries = mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale);
|
|
26
|
+
if (entries[0]) {
|
|
27
|
+
entries[0].ignoreTick = true;
|
|
28
|
+
}
|
|
29
|
+
return [{
|
|
30
|
+
formattedValue: undefined,
|
|
31
|
+
offset: scale.range()[0],
|
|
32
|
+
labelOffset: 0,
|
|
33
|
+
groupIndex: groups.length - 1
|
|
34
|
+
}, ...entries,
|
|
35
|
+
// Last tick
|
|
36
|
+
{
|
|
37
|
+
formattedValue: undefined,
|
|
38
|
+
offset: scale.range()[1],
|
|
39
|
+
labelOffset: 0,
|
|
40
|
+
groupIndex: groups.length - 1
|
|
41
|
+
}];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// scale type = 'point'
|
|
45
|
+
return mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale);
|
|
46
|
+
}, [scale, tickInterval, groups, tickPlacement, tickLabelPlacement]);
|
|
47
|
+
}
|
|
48
|
+
function mapToGrouping(tickValues, groups, tickPlacement, tickLabelPlacement, scale) {
|
|
49
|
+
const allTickItems = [];
|
|
50
|
+
// Map to keep track of offsets and their corresponding tick indexes
|
|
51
|
+
// Used to remove redundant ticks when they are in the same position
|
|
52
|
+
const dataIndexToTickIndex = new Map();
|
|
53
|
+
let currentValueCount = 0;
|
|
54
|
+
for (let groupIndex = 0; groupIndex < groups.length; groupIndex += 1) {
|
|
55
|
+
for (let dataIndex = 0; dataIndex < tickValues.length; dataIndex += 1) {
|
|
56
|
+
const tickValue = tickValues[dataIndex];
|
|
57
|
+
const groupValue = groups[groupIndex].getValue(tickValue, dataIndex);
|
|
58
|
+
const lastItem = allTickItems[allTickItems.length - 1];
|
|
59
|
+
|
|
60
|
+
// Check if this is a new unique value for this group
|
|
61
|
+
const isNew = lastItem?.value !== groupValue || lastItem?.groupIndex !== groupIndex;
|
|
62
|
+
if (isNew) {
|
|
63
|
+
currentValueCount = 1;
|
|
64
|
+
// Calculate tick offset
|
|
65
|
+
const tickOffset = isBandScale(scale) ? scale(tickValue) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[tickPlacement] * scale.step() : scale(tickValue);
|
|
66
|
+
|
|
67
|
+
// Calculate the label offset
|
|
68
|
+
const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]);
|
|
69
|
+
|
|
70
|
+
// Add a new item
|
|
71
|
+
allTickItems.push({
|
|
72
|
+
value: groupValue,
|
|
73
|
+
formattedValue: `${groupValue}`,
|
|
74
|
+
offset: tickOffset,
|
|
75
|
+
groupIndex,
|
|
76
|
+
dataIndex,
|
|
77
|
+
ignoreTick: false,
|
|
78
|
+
labelOffset
|
|
79
|
+
});
|
|
80
|
+
if (!dataIndexToTickIndex.has(dataIndex)) {
|
|
81
|
+
dataIndexToTickIndex.set(dataIndex, new Set());
|
|
82
|
+
}
|
|
83
|
+
const tickIndexes = dataIndexToTickIndex.get(dataIndex);
|
|
84
|
+
for (const previousIndex of tickIndexes.values()) {
|
|
85
|
+
allTickItems[previousIndex].ignoreTick = true;
|
|
86
|
+
}
|
|
87
|
+
tickIndexes.add(allTickItems.length - 1);
|
|
88
|
+
} else {
|
|
89
|
+
currentValueCount += 1;
|
|
90
|
+
|
|
91
|
+
// Calculate the label offset
|
|
92
|
+
const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]);
|
|
93
|
+
lastItem.labelOffset = labelOffset;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return allTickItems;
|
|
98
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -10,6 +10,8 @@ import { timer, now, timeout, timerFlush } from '@mui/x-charts-vendor/d3-timer';
|
|
|
10
10
|
* stopped.
|
|
11
11
|
*/
|
|
12
12
|
export class Transition {
|
|
13
|
+
elapsed = 0;
|
|
14
|
+
timer = null;
|
|
13
15
|
/**
|
|
14
16
|
* Create a new ResumableTransition.
|
|
15
17
|
* @param duration Duration in milliseconds
|
|
@@ -17,11 +19,6 @@ export class Transition {
|
|
|
17
19
|
* @param onTick Callback function called on each animation frame with the eased time in range [0, 1].
|
|
18
20
|
*/
|
|
19
21
|
constructor(duration, easingFn, onTick) {
|
|
20
|
-
this.duration = void 0;
|
|
21
|
-
this.elapsed = 0;
|
|
22
|
-
this.easingFn = void 0;
|
|
23
|
-
this.timer = null;
|
|
24
|
-
this.onTickCallback = void 0;
|
|
25
22
|
this.duration = duration;
|
|
26
23
|
this.easingFn = easingFn;
|
|
27
24
|
this.onTickCallback = onTick;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
let cartesianInstance;
|
|
2
2
|
let polarInstance;
|
|
3
3
|
class CartesianSeriesTypes {
|
|
4
|
+
types = (() => new Set())();
|
|
4
5
|
constructor() {
|
|
5
|
-
this.types = new Set();
|
|
6
6
|
if (cartesianInstance) {
|
|
7
7
|
throw new Error('You can only create one instance!');
|
|
8
8
|
}
|
|
@@ -16,8 +16,8 @@ class CartesianSeriesTypes {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
class PolarSeriesTypes {
|
|
19
|
+
types = (() => new Set())();
|
|
19
20
|
constructor() {
|
|
20
|
-
this.types = new Set();
|
|
21
21
|
if (polarInstance) {
|
|
22
22
|
throw new Error('You can only create one instance!');
|
|
23
23
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ContinuousScaleName, D3ContinuousScale } from "../models/axis.js";
|
|
2
|
-
export declare function getScale(scaleType: ContinuousScaleName, domain: any[], range: any[]): D3ContinuousScale;
|
|
2
|
+
export declare function getScale(scaleType: ContinuousScaleName, domain: readonly any[], range: readonly any[]): D3ContinuousScale;
|
package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AxisId, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from "../../../../models/axis.js";
|
|
1
|
+
import { AxisId, ChartsXAxisProps, ChartsYAxisProps, ContinuousScaleName, ScaleName } from "../../../../models/axis.js";
|
|
2
2
|
import { CartesianChartSeriesType } from "../../../../models/seriesType/config.js";
|
|
3
3
|
import { ProcessedSeries } from "../../corePlugins/useChartSeries/index.js";
|
|
4
4
|
import { AxisConfig } from "../../../../models/index.js";
|
|
@@ -19,4 +19,6 @@ export declare function createAxisFilterMapper(params: {
|
|
|
19
19
|
formattedSeries: ProcessedSeries;
|
|
20
20
|
direction: 'y';
|
|
21
21
|
}): (axis: AxisConfig<ScaleName, any, ChartsYAxisProps>, axisIndex: number) => ExtremumFilter | null;
|
|
22
|
+
export declare function createDiscreteScaleGetAxisFilter(axisData: AxisConfig['data'], zoomStart: number, zoomEnd: number, direction: 'x' | 'y'): ExtremumFilter;
|
|
23
|
+
export declare function createContinuousScaleGetAxisFilter(scaleType: ContinuousScaleName | undefined, extrema: readonly [number, number], zoomStart: number, zoomEnd: number, direction: 'x' | 'y', axisData: AxisConfig['data']): ExtremumFilter;
|
|
22
24
|
export declare const createGetAxisFilters: (filters: ZoomAxisFilters) => GetZoomAxisFilters;
|
package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.js
CHANGED
|
@@ -18,32 +18,41 @@ export function createAxisFilterMapper({
|
|
|
18
18
|
// No zoom, or zoom with all data visible
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
|
-
let extremums = [];
|
|
22
21
|
const scaleType = axis.scaleType;
|
|
23
22
|
if (scaleType === 'point' || scaleType === 'band') {
|
|
24
|
-
|
|
25
|
-
} else {
|
|
26
|
-
extremums = getAxisExtremum(axis, direction, seriesConfig, axisIndex, formattedSeries);
|
|
23
|
+
return createDiscreteScaleGetAxisFilter(axis.data, zoom.start, zoom.end, direction);
|
|
27
24
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
25
|
+
return createContinuousScaleGetAxisFilter(scaleType, getAxisExtremum(axis, direction, seriesConfig, axisIndex, formattedSeries), zoom.start, zoom.end, direction, axis.data);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function createDiscreteScaleGetAxisFilter(axisData, zoomStart, zoomEnd, direction) {
|
|
29
|
+
const maxIndex = axisData?.length ?? 0;
|
|
30
|
+
const minVal = Math.floor(zoomStart * maxIndex / 100);
|
|
31
|
+
const maxVal = Math.ceil(zoomEnd * maxIndex / 100);
|
|
32
|
+
return function filterAxis(value, dataIndex) {
|
|
33
|
+
const val = value[direction] ?? axisData?.[dataIndex];
|
|
34
|
+
if (val == null) {
|
|
35
|
+
// If the value does not exist because of missing data point, or out of range index, we just ignore.
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return dataIndex >= minVal && dataIndex < maxVal;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function createContinuousScaleGetAxisFilter(scaleType, extrema, zoomStart, zoomEnd, direction, axisData) {
|
|
42
|
+
let min;
|
|
43
|
+
let max;
|
|
44
|
+
[min, max] = getScale(scaleType ?? 'linear', extrema, [0, 100]).nice().domain();
|
|
45
|
+
min = min instanceof Date ? min.getTime() : min;
|
|
46
|
+
max = max instanceof Date ? max.getTime() : max;
|
|
47
|
+
const minVal = min + zoomStart * (max - min) / 100;
|
|
48
|
+
const maxVal = min + zoomEnd * (max - min) / 100;
|
|
49
|
+
return function filterAxis(value, dataIndex) {
|
|
50
|
+
const val = value[direction] ?? axisData?.[dataIndex];
|
|
51
|
+
if (val == null) {
|
|
52
|
+
// If the value does not exist because of missing data point, or out of range index, we just ignore.
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return val >= minVal && val <= maxVal;
|
|
47
56
|
};
|
|
48
57
|
}
|
|
49
58
|
export const createGetAxisFilters = filters => ({
|
|
@@ -3,4 +3,4 @@ import { CartesianChartSeriesType } from "../../../../models/seriesType/config.j
|
|
|
3
3
|
import { ChartSeriesConfig } from "../../models/seriesConfig/index.js";
|
|
4
4
|
import { ProcessedSeries } from "../../corePlugins/useChartSeries/useChartSeries.types.js";
|
|
5
5
|
import { GetZoomAxisFilters } from "./zoom.types.js";
|
|
6
|
-
export declare const getAxisExtremum: <T extends CartesianChartSeriesType>(axis: AxisConfig, axisDirection: "x" | "y", seriesConfig: ChartSeriesConfig<T>, axisIndex: number, formattedSeries: ProcessedSeries<T>, getFilters?: GetZoomAxisFilters) => number
|
|
6
|
+
export declare const getAxisExtremum: <T extends CartesianChartSeriesType>(axis: AxisConfig, axisDirection: "x" | "y", seriesConfig: ChartSeriesConfig<T>, axisIndex: number, formattedSeries: ProcessedSeries<T>, getFilters?: GetZoomAxisFilters) => [number, number];
|
|
@@ -8,4 +8,4 @@ export declare function getAxisIndex(axisConfig: ComputedAxis, pointerValue: num
|
|
|
8
8
|
* For a pointer coordinate, this function returns the value associated.
|
|
9
9
|
* Returns `null` if the coordinate has no value associated.
|
|
10
10
|
*/
|
|
11
|
-
export declare function getAxisValue(axisConfig: ComputedAxis, pointerValue: number, dataIndex: number): number | Date | null;
|
|
11
|
+
export declare function getAxisValue(axisConfig: ComputedAxis, pointerValue: number, dataIndex: number | null): number | Date | null;
|
|
@@ -52,13 +52,12 @@ export function getAxisValue(axisConfig, pointerValue, dataIndex) {
|
|
|
52
52
|
data: axisData
|
|
53
53
|
} = axisConfig;
|
|
54
54
|
if (!isBandScale(scale)) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return value;
|
|
55
|
+
if (dataIndex === null) {
|
|
56
|
+
return scale.invert(pointerValue);
|
|
58
57
|
}
|
|
59
58
|
return axisData[dataIndex];
|
|
60
59
|
}
|
|
61
|
-
if (dataIndex < 0 || dataIndex >= axisData.length) {
|
|
60
|
+
if (dataIndex === null || dataIndex < 0 || dataIndex >= axisData.length) {
|
|
62
61
|
return null;
|
|
63
62
|
}
|
|
64
63
|
return axisData[dataIndex];
|
|
@@ -37,13 +37,13 @@ function valueGetter(value, axes, indexes, ids = axes.axisIds[0]) {
|
|
|
37
37
|
return Array.isArray(ids) ? ids.map((id, axisIndex) => getAxisValue(axes.axis[id], value, indexes[axisIndex])) : getAxisValue(axes.axis[ids], value, indexes);
|
|
38
38
|
}
|
|
39
39
|
export const selectorChartsInteractionXAxisValue = createSelector([selectorChartsInteractionPointerX, selectorChartXAxis, selectorChartsInteractionXAxisIndex, optionalGetAxisId], (x, xAxes, xIndex, id) => {
|
|
40
|
-
if (x === null ||
|
|
40
|
+
if (x === null || xAxes.axisIds.length === 0) {
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
43
43
|
return valueGetter(x, xAxes, xIndex, id);
|
|
44
44
|
});
|
|
45
45
|
export const selectorChartsInteractionYAxisValue = createSelector([selectorChartsInteractionPointerY, selectorChartYAxis, selectorChartsInteractionYAxisIndex, optionalGetAxisId], (y, yAxes, yIndex, id) => {
|
|
46
|
-
if (y === null ||
|
|
46
|
+
if (y === null || yAxes.axisIds.length === 0) {
|
|
47
47
|
return null;
|
|
48
48
|
}
|
|
49
49
|
return valueGetter(y, yAxes, yIndex, id);
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
export class ChartStore {
|
|
2
2
|
constructor(value) {
|
|
3
|
-
this.value = void 0;
|
|
4
|
-
this.listeners = void 0;
|
|
5
|
-
this.subscribe = fn => {
|
|
6
|
-
this.listeners.add(fn);
|
|
7
|
-
return () => {
|
|
8
|
-
this.listeners.delete(fn);
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
this.getSnapshot = () => {
|
|
12
|
-
return this.value;
|
|
13
|
-
};
|
|
14
|
-
this.update = updater => {
|
|
15
|
-
const newState = updater(this.value);
|
|
16
|
-
if (newState !== this.value) {
|
|
17
|
-
this.value = newState;
|
|
18
|
-
this.listeners.forEach(l => l(newState));
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
3
|
this.value = value;
|
|
22
4
|
this.listeners = new Set();
|
|
23
5
|
}
|
|
6
|
+
subscribe = fn => {
|
|
7
|
+
this.listeners.add(fn);
|
|
8
|
+
return () => {
|
|
9
|
+
this.listeners.delete(fn);
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
getSnapshot = () => {
|
|
13
|
+
return this.value;
|
|
14
|
+
};
|
|
15
|
+
update = updater => {
|
|
16
|
+
const newState = updater(this.value);
|
|
17
|
+
if (newState !== this.value) {
|
|
18
|
+
this.value = newState;
|
|
19
|
+
this.listeners.forEach(l => l(newState));
|
|
20
|
+
}
|
|
21
|
+
};
|
|
24
22
|
}
|
package/esm/models/axis.d.ts
CHANGED
|
@@ -180,6 +180,50 @@ export interface ChartsRadiusAxisProps extends ChartsAxisProps {
|
|
|
180
180
|
}
|
|
181
181
|
export type ScaleName = keyof AxisScaleConfig;
|
|
182
182
|
export type ContinuousScaleName = 'linear' | 'log' | 'symlog' | 'pow' | 'sqrt' | 'time' | 'utc';
|
|
183
|
+
export type AxisGroup = {
|
|
184
|
+
/**
|
|
185
|
+
* The function used to return the value for this group.
|
|
186
|
+
*
|
|
187
|
+
* @param {any} value The value of the axis item.
|
|
188
|
+
* @param {number} dataIndex The index of the data item.
|
|
189
|
+
* @returns {string | number | Date} The value that will be used to group the axis items.
|
|
190
|
+
*/
|
|
191
|
+
getValue: (value: any, dataIndex: number) => string | number | Date;
|
|
192
|
+
/**
|
|
193
|
+
* The size of the tick in pixels.
|
|
194
|
+
* @default 6
|
|
195
|
+
*/
|
|
196
|
+
tickSize?: number;
|
|
197
|
+
/**
|
|
198
|
+
* The style applied to ticks text.
|
|
199
|
+
*/
|
|
200
|
+
tickLabelStyle?: ChartsTextProps['style'];
|
|
201
|
+
};
|
|
202
|
+
export type AxisGroups = {
|
|
203
|
+
/**
|
|
204
|
+
* Each group will have a label that is the stringified value of the group.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* If the axis is grouped by day, month and year.
|
|
208
|
+
*
|
|
209
|
+
* ```tsx
|
|
210
|
+
* [
|
|
211
|
+
* { getValue: getDate },
|
|
212
|
+
* { getValue: getMonth },
|
|
213
|
+
* { getValue: getFullYear }
|
|
214
|
+
* ]
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* Then the axis will have three rows, one for each group.
|
|
218
|
+
*
|
|
219
|
+
* ```bash
|
|
220
|
+
* | 31 | 1 | 2 |
|
|
221
|
+
* | Jan | Feb |
|
|
222
|
+
* | 2021 |
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
groups?: AxisGroup[];
|
|
226
|
+
};
|
|
183
227
|
export interface AxisScaleConfig {
|
|
184
228
|
band: {
|
|
185
229
|
scaleType: 'band';
|
|
@@ -197,12 +241,12 @@ export interface AxisScaleConfig {
|
|
|
197
241
|
*/
|
|
198
242
|
barGapRatio: number;
|
|
199
243
|
colorMap?: OrdinalColorConfig | ContinuousColorConfig | PiecewiseColorConfig;
|
|
200
|
-
} & Pick<TickParams, 'tickPlacement' | 'tickLabelPlacement'>;
|
|
244
|
+
} & AxisGroups & Pick<TickParams, 'tickPlacement' | 'tickLabelPlacement'>;
|
|
201
245
|
point: {
|
|
202
246
|
scaleType: 'point';
|
|
203
247
|
scale: ScalePoint<number | Date | string>;
|
|
204
248
|
colorMap?: OrdinalColorConfig | ContinuousColorConfig | PiecewiseColorConfig;
|
|
205
|
-
};
|
|
249
|
+
} & AxisGroups;
|
|
206
250
|
log: {
|
|
207
251
|
scaleType: 'log';
|
|
208
252
|
scale: ScaleLogarithmic<number, number>;
|
|
@@ -10,12 +10,10 @@ export function reactToWebComponent(ReactComponent, options, renderer) {
|
|
|
10
10
|
static get observedAttributes() {
|
|
11
11
|
return [];
|
|
12
12
|
}
|
|
13
|
+
[connectedSymbol] = true;
|
|
14
|
+
[propsSymbol] = (() => ({}))();
|
|
13
15
|
constructor() {
|
|
14
16
|
super();
|
|
15
|
-
this[connectedSymbol] = true;
|
|
16
|
-
this[contextSymbol] = void 0;
|
|
17
|
-
this[propsSymbol] = {};
|
|
18
|
-
this.container = void 0;
|
|
19
17
|
if (options.shadow) {
|
|
20
18
|
this.container = this.attachShadow({
|
|
21
19
|
mode: options.shadow
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ScaleBand, ScalePoint } from '@mui/x-charts-vendor/d3-scale';
|
|
2
|
+
import { AxisConfig, type AxisGroup } from "../models/axis.js";
|
|
3
|
+
import type { TickParams } from "./useTicks.js";
|
|
4
|
+
export type GroupedTickItemType = {
|
|
5
|
+
/**
|
|
6
|
+
* This property is undefined only if it's the tick closing the last band
|
|
7
|
+
*/
|
|
8
|
+
value?: any;
|
|
9
|
+
formattedValue?: string;
|
|
10
|
+
offset: number;
|
|
11
|
+
labelOffset: number;
|
|
12
|
+
/**
|
|
13
|
+
* In band scales, we remove some redundant ticks.
|
|
14
|
+
*/
|
|
15
|
+
ignoreTick?: boolean;
|
|
16
|
+
dataIndex?: number;
|
|
17
|
+
/**
|
|
18
|
+
* The index of the group this tick belongs to. If `getGrouping` returns `[[0, 1], [2, 3]]`
|
|
19
|
+
* both ticks with value `0` and `2` will have `groupIndex: 0`, and both ticks with value `1` and `3` will have `groupIndex: 1`.
|
|
20
|
+
*/
|
|
21
|
+
groupIndex?: number;
|
|
22
|
+
};
|
|
23
|
+
export declare function useTicksGrouped(options: {
|
|
24
|
+
scale: ScaleBand<any> | ScalePoint<any>;
|
|
25
|
+
valueFormatter?: AxisConfig['valueFormatter'];
|
|
26
|
+
direction: 'x' | 'y';
|
|
27
|
+
groups: AxisGroup[];
|
|
28
|
+
} & Pick<TickParams, 'tickNumber' | 'tickInterval' | 'tickPlacement' | 'tickLabelPlacement'>): GroupedTickItemType[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.useTicksGrouped = useTicksGrouped;
|
|
9
|
+
var React = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _isBandScale = require("../internals/isBandScale");
|
|
11
|
+
const offsetRatio = {
|
|
12
|
+
start: 0,
|
|
13
|
+
extremities: 0,
|
|
14
|
+
end: 1,
|
|
15
|
+
middle: 0.5,
|
|
16
|
+
tick: 0
|
|
17
|
+
};
|
|
18
|
+
function useTicksGrouped(options) {
|
|
19
|
+
const {
|
|
20
|
+
scale,
|
|
21
|
+
tickInterval,
|
|
22
|
+
tickLabelPlacement = 'middle',
|
|
23
|
+
tickPlacement = 'extremities',
|
|
24
|
+
groups
|
|
25
|
+
} = options;
|
|
26
|
+
return React.useMemo(() => {
|
|
27
|
+
const domain = scale.domain();
|
|
28
|
+
const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain;
|
|
29
|
+
if (scale.bandwidth() > 0) {
|
|
30
|
+
// scale type = 'band'
|
|
31
|
+
const entries = mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale);
|
|
32
|
+
if (entries[0]) {
|
|
33
|
+
entries[0].ignoreTick = true;
|
|
34
|
+
}
|
|
35
|
+
return [{
|
|
36
|
+
formattedValue: undefined,
|
|
37
|
+
offset: scale.range()[0],
|
|
38
|
+
labelOffset: 0,
|
|
39
|
+
groupIndex: groups.length - 1
|
|
40
|
+
}, ...entries,
|
|
41
|
+
// Last tick
|
|
42
|
+
{
|
|
43
|
+
formattedValue: undefined,
|
|
44
|
+
offset: scale.range()[1],
|
|
45
|
+
labelOffset: 0,
|
|
46
|
+
groupIndex: groups.length - 1
|
|
47
|
+
}];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// scale type = 'point'
|
|
51
|
+
return mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale);
|
|
52
|
+
}, [scale, tickInterval, groups, tickPlacement, tickLabelPlacement]);
|
|
53
|
+
}
|
|
54
|
+
function mapToGrouping(tickValues, groups, tickPlacement, tickLabelPlacement, scale) {
|
|
55
|
+
const allTickItems = [];
|
|
56
|
+
// Map to keep track of offsets and their corresponding tick indexes
|
|
57
|
+
// Used to remove redundant ticks when they are in the same position
|
|
58
|
+
const dataIndexToTickIndex = new Map();
|
|
59
|
+
let currentValueCount = 0;
|
|
60
|
+
for (let groupIndex = 0; groupIndex < groups.length; groupIndex += 1) {
|
|
61
|
+
for (let dataIndex = 0; dataIndex < tickValues.length; dataIndex += 1) {
|
|
62
|
+
const tickValue = tickValues[dataIndex];
|
|
63
|
+
const groupValue = groups[groupIndex].getValue(tickValue, dataIndex);
|
|
64
|
+
const lastItem = allTickItems[allTickItems.length - 1];
|
|
65
|
+
|
|
66
|
+
// Check if this is a new unique value for this group
|
|
67
|
+
const isNew = lastItem?.value !== groupValue || lastItem?.groupIndex !== groupIndex;
|
|
68
|
+
if (isNew) {
|
|
69
|
+
currentValueCount = 1;
|
|
70
|
+
// Calculate tick offset
|
|
71
|
+
const tickOffset = (0, _isBandScale.isBandScale)(scale) ? scale(tickValue) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[tickPlacement] * scale.step() : scale(tickValue);
|
|
72
|
+
|
|
73
|
+
// Calculate the label offset
|
|
74
|
+
const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]);
|
|
75
|
+
|
|
76
|
+
// Add a new item
|
|
77
|
+
allTickItems.push({
|
|
78
|
+
value: groupValue,
|
|
79
|
+
formattedValue: `${groupValue}`,
|
|
80
|
+
offset: tickOffset,
|
|
81
|
+
groupIndex,
|
|
82
|
+
dataIndex,
|
|
83
|
+
ignoreTick: false,
|
|
84
|
+
labelOffset
|
|
85
|
+
});
|
|
86
|
+
if (!dataIndexToTickIndex.has(dataIndex)) {
|
|
87
|
+
dataIndexToTickIndex.set(dataIndex, new Set());
|
|
88
|
+
}
|
|
89
|
+
const tickIndexes = dataIndexToTickIndex.get(dataIndex);
|
|
90
|
+
for (const previousIndex of tickIndexes.values()) {
|
|
91
|
+
allTickItems[previousIndex].ignoreTick = true;
|
|
92
|
+
}
|
|
93
|
+
tickIndexes.add(allTickItems.length - 1);
|
|
94
|
+
} else {
|
|
95
|
+
currentValueCount += 1;
|
|
96
|
+
|
|
97
|
+
// Calculate the label offset
|
|
98
|
+
const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]);
|
|
99
|
+
lastItem.labelOffset = labelOffset;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return allTickItems;
|
|
104
|
+
}
|
package/index.js
CHANGED
|
@@ -15,6 +15,8 @@ var _d3Timer = require("@mui/x-charts-vendor/d3-timer");
|
|
|
15
15
|
* stopped.
|
|
16
16
|
*/
|
|
17
17
|
class Transition {
|
|
18
|
+
elapsed = 0;
|
|
19
|
+
timer = null;
|
|
18
20
|
/**
|
|
19
21
|
* Create a new ResumableTransition.
|
|
20
22
|
* @param duration Duration in milliseconds
|
|
@@ -22,11 +24,6 @@ class Transition {
|
|
|
22
24
|
* @param onTick Callback function called on each animation frame with the eased time in range [0, 1].
|
|
23
25
|
*/
|
|
24
26
|
constructor(duration, easingFn, onTick) {
|
|
25
|
-
this.duration = void 0;
|
|
26
|
-
this.elapsed = 0;
|
|
27
|
-
this.easingFn = void 0;
|
|
28
|
-
this.timer = null;
|
|
29
|
-
this.onTickCallback = void 0;
|
|
30
27
|
this.duration = duration;
|
|
31
28
|
this.easingFn = easingFn;
|
|
32
29
|
this.onTickCallback = onTick;
|
package/internals/configInit.js
CHANGED
|
@@ -7,8 +7,8 @@ exports.polarSeriesTypes = exports.cartesianSeriesTypes = void 0;
|
|
|
7
7
|
let cartesianInstance;
|
|
8
8
|
let polarInstance;
|
|
9
9
|
class CartesianSeriesTypes {
|
|
10
|
+
types = new Set();
|
|
10
11
|
constructor() {
|
|
11
|
-
this.types = new Set();
|
|
12
12
|
if (cartesianInstance) {
|
|
13
13
|
throw new Error('You can only create one instance!');
|
|
14
14
|
}
|
|
@@ -22,8 +22,8 @@ class CartesianSeriesTypes {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
class PolarSeriesTypes {
|
|
25
|
+
types = new Set();
|
|
25
26
|
constructor() {
|
|
26
|
-
this.types = new Set();
|
|
27
27
|
if (polarInstance) {
|
|
28
28
|
throw new Error('You can only create one instance!');
|
|
29
29
|
}
|
package/internals/getScale.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ContinuousScaleName, D3ContinuousScale } from "../models/axis.js";
|
|
2
|
-
export declare function getScale(scaleType: ContinuousScaleName, domain: any[], range: any[]): D3ContinuousScale;
|
|
2
|
+
export declare function getScale(scaleType: ContinuousScaleName, domain: readonly any[], range: readonly any[]): D3ContinuousScale;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AxisId, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from "../../../../models/axis.js";
|
|
1
|
+
import { AxisId, ChartsXAxisProps, ChartsYAxisProps, ContinuousScaleName, ScaleName } from "../../../../models/axis.js";
|
|
2
2
|
import { CartesianChartSeriesType } from "../../../../models/seriesType/config.js";
|
|
3
3
|
import { ProcessedSeries } from "../../corePlugins/useChartSeries/index.js";
|
|
4
4
|
import { AxisConfig } from "../../../../models/index.js";
|
|
@@ -19,4 +19,6 @@ export declare function createAxisFilterMapper(params: {
|
|
|
19
19
|
formattedSeries: ProcessedSeries;
|
|
20
20
|
direction: 'y';
|
|
21
21
|
}): (axis: AxisConfig<ScaleName, any, ChartsYAxisProps>, axisIndex: number) => ExtremumFilter | null;
|
|
22
|
+
export declare function createDiscreteScaleGetAxisFilter(axisData: AxisConfig['data'], zoomStart: number, zoomEnd: number, direction: 'x' | 'y'): ExtremumFilter;
|
|
23
|
+
export declare function createContinuousScaleGetAxisFilter(scaleType: ContinuousScaleName | undefined, extrema: readonly [number, number], zoomStart: number, zoomEnd: number, direction: 'x' | 'y', axisData: AxisConfig['data']): ExtremumFilter;
|
|
22
24
|
export declare const createGetAxisFilters: (filters: ZoomAxisFilters) => GetZoomAxisFilters;
|