@mui/x-charts 8.18.0 → 8.20.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.
Files changed (140) hide show
  1. package/BarChart/seriesConfig/bar/seriesProcessor.js +15 -9
  2. package/CHANGELOG.md +175 -0
  3. package/ChartsGrid/ChartsHorizontalGrid.js +5 -1
  4. package/ChartsGrid/ChartsVerticalGrid.js +5 -1
  5. package/ChartsSurface/ChartsSurface.js +5 -2
  6. package/ChartsTooltip/ChartsTooltipContainer.js +1 -1
  7. package/LineChart/seriesConfig/seriesProcessor.js +15 -10
  8. package/PieChart/PieArcPlot.js +5 -3
  9. package/RadarChart/RadarSeriesPlot/RadarSeriesArea.js +2 -2
  10. package/RadarChart/RadarSeriesPlot/RadarSeriesPlot.js +2 -2
  11. package/RadarChart/RadarSeriesPlot/useInteractionAllItemProps.d.ts +7 -0
  12. package/RadarChart/RadarSeriesPlot/useInteractionAllItemProps.js +26 -0
  13. package/esm/BarChart/seriesConfig/bar/seriesProcessor.js +15 -9
  14. package/esm/ChartsGrid/ChartsHorizontalGrid.js +5 -1
  15. package/esm/ChartsGrid/ChartsVerticalGrid.js +5 -1
  16. package/esm/ChartsSurface/ChartsSurface.js +5 -2
  17. package/esm/ChartsTooltip/ChartsTooltipContainer.js +1 -1
  18. package/esm/LineChart/seriesConfig/seriesProcessor.js +15 -10
  19. package/esm/PieChart/PieArcPlot.js +5 -3
  20. package/esm/RadarChart/RadarSeriesPlot/RadarSeriesArea.js +1 -1
  21. package/esm/RadarChart/RadarSeriesPlot/RadarSeriesPlot.js +1 -1
  22. package/esm/RadarChart/RadarSeriesPlot/useInteractionAllItemProps.d.ts +7 -0
  23. package/esm/RadarChart/RadarSeriesPlot/useInteractionAllItemProps.js +18 -0
  24. package/esm/hooks/useBarSeries.js +3 -5
  25. package/esm/hooks/useInteractionItemProps.d.ts +0 -5
  26. package/esm/hooks/useInteractionItemProps.js +0 -11
  27. package/esm/hooks/useLineSeries.js +3 -5
  28. package/esm/hooks/usePieSeries.js +3 -5
  29. package/esm/hooks/useRadarSeries.js +3 -5
  30. package/esm/hooks/useScatterSeries.js +3 -5
  31. package/esm/hooks/useTicks.js +12 -3
  32. package/esm/index.d.ts +2 -1
  33. package/esm/index.js +2 -1
  34. package/esm/internals/domUtils.js +30 -14
  35. package/esm/internals/getScale.d.ts +2 -1
  36. package/esm/internals/index.d.ts +1 -1
  37. package/esm/internals/index.js +1 -1
  38. package/esm/internals/plugins/corePlugins/useChartAnimation/useChartAnimation.selectors.js +2 -2
  39. package/esm/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.js +5 -6
  40. package/esm/internals/plugins/corePlugins/useChartExperimentalFeature/useChartExperimentalFeature.selectors.js +2 -2
  41. package/esm/internals/plugins/corePlugins/useChartId/useChartId.selectors.js +2 -2
  42. package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +4 -1
  43. package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +3 -1
  44. package/esm/internals/plugins/corePlugins/useChartSeries/processSeries.d.ts +16 -10
  45. package/esm/internals/plugins/corePlugins/useChartSeries/processSeries.js +20 -12
  46. package/esm/internals/plugins/corePlugins/useChartSeries/useChartSeries.js +5 -7
  47. package/esm/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.d.ts +11 -4
  48. package/esm/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.js +14 -5
  49. package/esm/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.d.ts +3 -2
  50. package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.d.ts +1 -1
  51. package/esm/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.js +15 -15
  52. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts +1 -1
  53. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisPreview.selectors.js +5 -5
  54. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.ts +3 -0
  55. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.js +11 -11
  56. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +5 -6
  57. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianInteraction.selectors.js +7 -8
  58. package/esm/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.js +2 -2
  59. package/esm/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.selectors.js +2 -2
  60. package/esm/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.js +16 -12
  61. package/esm/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.selectors.js +15 -16
  62. package/esm/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.types.d.ts +4 -0
  63. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.js +8 -8
  64. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartTooltip.selectors.d.ts +1 -1
  65. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartTooltip.selectors.js +4 -4
  66. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js +15 -10
  67. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.js +11 -11
  68. package/esm/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.selectors.js +6 -6
  69. package/esm/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarInteraction.selectors.js +7 -8
  70. package/esm/internals/plugins/featurePlugins/useChartZAxis/useChartZAxis.selectors.js +2 -2
  71. package/esm/internals/plugins/utils/selectors.d.ts +1 -14
  72. package/esm/internals/plugins/utils/selectors.js +1 -5
  73. package/esm/internals/seriesSelectorOfType.d.ts +20 -0
  74. package/esm/internals/seriesSelectorOfType.js +38 -0
  75. package/esm/models/seriesType/config.d.ts +2 -2
  76. package/esm/utils/index.d.ts +4 -0
  77. package/esm/utils/index.js +5 -0
  78. package/esm/utils/niceDomain.d.ts +20 -0
  79. package/esm/utils/niceDomain.js +24 -0
  80. package/hooks/useBarSeries.js +3 -6
  81. package/hooks/useInteractionItemProps.d.ts +0 -5
  82. package/hooks/useInteractionItemProps.js +1 -13
  83. package/hooks/useLineSeries.js +3 -6
  84. package/hooks/usePieSeries.js +3 -6
  85. package/hooks/useRadarSeries.js +3 -6
  86. package/hooks/useScatterSeries.js +3 -6
  87. package/hooks/useTicks.js +12 -3
  88. package/index.d.ts +2 -1
  89. package/index.js +13 -1
  90. package/internals/domUtils.js +30 -14
  91. package/internals/getScale.d.ts +2 -1
  92. package/internals/index.d.ts +1 -1
  93. package/internals/index.js +4 -4
  94. package/internals/plugins/corePlugins/useChartAnimation/useChartAnimation.selectors.js +2 -2
  95. package/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.js +4 -5
  96. package/internals/plugins/corePlugins/useChartExperimentalFeature/useChartExperimentalFeature.selectors.js +2 -2
  97. package/internals/plugins/corePlugins/useChartId/useChartId.selectors.js +2 -2
  98. package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +4 -1
  99. package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +3 -1
  100. package/internals/plugins/corePlugins/useChartSeries/processSeries.d.ts +16 -10
  101. package/internals/plugins/corePlugins/useChartSeries/processSeries.js +23 -14
  102. package/internals/plugins/corePlugins/useChartSeries/useChartSeries.js +4 -6
  103. package/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.d.ts +11 -4
  104. package/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.js +15 -6
  105. package/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.d.ts +3 -2
  106. package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.d.ts +1 -1
  107. package/internals/plugins/featurePlugins/useChartBrush/useChartBrush.selectors.js +15 -15
  108. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.d.ts +1 -1
  109. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisPreview.selectors.js +5 -5
  110. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.ts +3 -0
  111. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.js +11 -11
  112. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +4 -5
  113. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianInteraction.selectors.js +6 -7
  114. package/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.js +2 -2
  115. package/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.selectors.js +2 -2
  116. package/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.js +16 -12
  117. package/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.selectors.js +14 -15
  118. package/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.types.d.ts +4 -0
  119. package/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.js +8 -8
  120. package/internals/plugins/featurePlugins/useChartInteraction/useChartTooltip.selectors.d.ts +1 -1
  121. package/internals/plugins/featurePlugins/useChartInteraction/useChartTooltip.selectors.js +4 -4
  122. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js +15 -10
  123. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.js +11 -11
  124. package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.selectors.js +6 -6
  125. package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarInteraction.selectors.js +6 -7
  126. package/internals/plugins/featurePlugins/useChartZAxis/useChartZAxis.selectors.js +2 -2
  127. package/internals/plugins/utils/selectors.d.ts +1 -14
  128. package/internals/plugins/utils/selectors.js +1 -8
  129. package/internals/seriesSelectorOfType.d.ts +20 -0
  130. package/internals/seriesSelectorOfType.js +46 -0
  131. package/models/seriesType/config.d.ts +2 -2
  132. package/package.json +4 -4
  133. package/utils/index.d.ts +4 -0
  134. package/utils/index.js +16 -0
  135. package/utils/niceDomain.d.ts +20 -0
  136. package/utils/niceDomain.js +29 -0
  137. package/esm/internals/createSeriesSelectorOfType.d.ts +0 -4
  138. package/esm/internals/createSeriesSelectorOfType.js +0 -45
  139. package/internals/createSeriesSelectorOfType.d.ts +0 -4
  140. package/internals/createSeriesSelectorOfType.js +0 -53
@@ -40,9 +40,11 @@ function PieArcPlot(props) {
40
40
  data
41
41
  });
42
42
  const {
43
- dataIndex: focusedIndex = -1
43
+ dataIndex,
44
+ seriesId,
45
+ seriesType
44
46
  } = useFocusedItem() ?? {};
45
- const focusedItem = focusedIndex !== -1 ? transformedData[focusedIndex] : null;
47
+ const focusedItem = dataIndex !== undefined && seriesId === id && seriesType === 'pie' ? transformedData[dataIndex] : null;
46
48
  if (data.length === 0) {
47
49
  return null;
48
50
  }
@@ -83,7 +85,7 @@ function PieArcPlot(props) {
83
85
  stroke: (theme.vars ?? theme).palette.text.primary,
84
86
  id: id,
85
87
  className: pieArcClasses.focusIndicator,
86
- dataIndex: focusedIndex,
88
+ dataIndex: focusedItem.dataIndex,
87
89
  isFaded: false,
88
90
  isHighlighted: false,
89
91
  isFocused: false,
@@ -8,7 +8,7 @@ import { useRadarSeriesData } from "./useRadarSeriesData.js";
8
8
  import { getAreaPath } from "./getAreaPath.js";
9
9
  import { useUtilityClasses } from "./radarSeriesPlotClasses.js";
10
10
  import { useItemHighlightedGetter } from "../../hooks/useItemHighlightedGetter.js";
11
- import { useInteractionAllItemProps } from "../../hooks/useInteractionItemProps.js";
11
+ import { useInteractionAllItemProps } from "./useInteractionAllItemProps.js";
12
12
  import { useRadarRotationIndex } from "./useRadarRotationIndex.js";
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
14
  export function getPathProps(params) {
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import PropTypes from 'prop-types';
3
3
  import { useRadarSeriesData } from "./useRadarSeriesData.js";
4
- import { useInteractionAllItemProps } from "../../hooks/useInteractionItemProps.js";
4
+ import { useInteractionAllItemProps } from "./useInteractionAllItemProps.js";
5
5
  import { useItemHighlightedGetter } from "../../hooks/useItemHighlightedGetter.js";
6
6
  import { useUtilityClasses } from "./radarSeriesPlotClasses.js";
7
7
  import { getPathProps } from "./RadarSeriesArea.js";
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ import { SeriesItemIdentifierWithData } from "../../models/seriesType/index.js";
3
+ export declare const useInteractionAllItemProps: (data: SeriesItemIdentifierWithData<"radar">[], skip?: boolean) => {
4
+ onPointerEnter?: () => void;
5
+ onPointerLeave?: () => void;
6
+ onPointerDown?: (event: React.PointerEvent) => void;
7
+ }[];
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ import { useChartContext } from "../../context/ChartProvider/useChartContext.js";
3
+ import { getInteractionItemProps } from "../../hooks/useInteractionItemProps.js";
4
+ export const useInteractionAllItemProps = (data, skip) => {
5
+ const {
6
+ instance
7
+ } = useChartContext();
8
+ const results = React.useMemo(() => {
9
+ return data.map(item => {
10
+ return skip ? {} : getInteractionItemProps(instance, {
11
+ type: 'radar',
12
+ seriesId: item.seriesId,
13
+ dataIndex: item.dataIndex
14
+ });
15
+ });
16
+ }, [data, instance, skip]);
17
+ return results;
18
+ };
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createSeriesSelectorsOfType, createAllSeriesSelectorOfType } from "../internals/createSeriesSelectorOfType.js";
4
- const useSelectorSeries = createSeriesSelectorsOfType('bar');
5
- const useSelectorSeriesContext = createAllSeriesSelectorOfType('bar');
3
+ import { useSeriesOfType, useAllSeriesOfType } from "../internals/seriesSelectorOfType.js";
6
4
 
7
5
  /**
8
6
  * Get access to the internal state of bar series.
@@ -27,7 +25,7 @@ const useSelectorSeriesContext = createAllSeriesSelectorOfType('bar');
27
25
  */
28
26
 
29
27
  export function useBarSeries(seriesIds) {
30
- return useSelectorSeries(seriesIds);
28
+ return useSeriesOfType('bar', seriesIds);
31
29
  }
32
30
 
33
31
  /**
@@ -39,5 +37,5 @@ export function useBarSeries(seriesIds) {
39
37
  * @returns the bar series
40
38
  */
41
39
  export function useBarSeriesContext() {
42
- return useSelectorSeriesContext();
40
+ return useAllSeriesOfType('bar');
43
41
  }
@@ -9,11 +9,6 @@ export declare const useInteractionItemProps: (data: SeriesItemIdentifierWithDat
9
9
  onPointerLeave?: () => void;
10
10
  onPointerDown?: (event: React.PointerEvent) => void;
11
11
  };
12
- export declare const useInteractionAllItemProps: (data: SeriesItemIdentifierWithData[], skip?: boolean) => {
13
- onPointerEnter?: () => void;
14
- onPointerLeave?: () => void;
15
- onPointerDown?: (event: React.PointerEvent) => void;
16
- }[];
17
12
  export declare function getInteractionItemProps(instance: ChartInstance<[UseChartInteractionSignature, UseChartHighlightSignature]>, item: ChartItemIdentifierWithData<ChartSeriesType>): {
18
13
  onPointerEnter?: () => void;
19
14
  onPointerLeave?: () => void;
@@ -39,17 +39,6 @@ export const useInteractionItemProps = (data, skip) => {
39
39
  onPointerDown
40
40
  }, [skip, onPointerEnter, onPointerLeave]);
41
41
  };
42
- export const useInteractionAllItemProps = (data, skip) => {
43
- const {
44
- instance
45
- } = useChartContext();
46
- const results = React.useMemo(() => {
47
- return data.map(item => {
48
- return skip ? {} : getInteractionItemProps(instance, item);
49
- });
50
- }, [data, instance, skip]);
51
- return results;
52
- };
53
42
  export function getInteractionItemProps(instance, item) {
54
43
  function onPointerEnter() {
55
44
  if (!item) {
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createSeriesSelectorsOfType, createAllSeriesSelectorOfType } from "../internals/createSeriesSelectorOfType.js";
4
- const useSelectorSeries = createSeriesSelectorsOfType('line');
5
- const useSelectorSeriesContext = createAllSeriesSelectorOfType('line');
3
+ import { useSeriesOfType, useAllSeriesOfType } from "../internals/seriesSelectorOfType.js";
6
4
 
7
5
  /**
8
6
  * Get access to the internal state of line series.
@@ -27,7 +25,7 @@ const useSelectorSeriesContext = createAllSeriesSelectorOfType('line');
27
25
  */
28
26
 
29
27
  export function useLineSeries(seriesIds) {
30
- return useSelectorSeries(seriesIds);
28
+ return useSeriesOfType('line', seriesIds);
31
29
  }
32
30
 
33
31
  /**
@@ -39,5 +37,5 @@ export function useLineSeries(seriesIds) {
39
37
  * @returns the line series
40
38
  */
41
39
  export function useLineSeriesContext() {
42
- return useSelectorSeriesContext();
40
+ return useAllSeriesOfType('line');
43
41
  }
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createSeriesSelectorsOfType, createAllSeriesSelectorOfType } from "../internals/createSeriesSelectorOfType.js";
4
- const useSelectorSeries = createSeriesSelectorsOfType('pie');
5
- const useSelectorSeriesContext = createAllSeriesSelectorOfType('pie');
3
+ import { useSeriesOfType, useAllSeriesOfType } from "../internals/seriesSelectorOfType.js";
6
4
 
7
5
  /**
8
6
  * Get access to the internal state of pie series.
@@ -27,7 +25,7 @@ const useSelectorSeriesContext = createAllSeriesSelectorOfType('pie');
27
25
  */
28
26
 
29
27
  export function usePieSeries(seriesIds) {
30
- return useSelectorSeries(seriesIds);
28
+ return useSeriesOfType('pie', seriesIds);
31
29
  }
32
30
 
33
31
  /**
@@ -38,5 +36,5 @@ export function usePieSeries(seriesIds) {
38
36
  * @returns the pie series
39
37
  */
40
38
  export function usePieSeriesContext() {
41
- return useSelectorSeriesContext();
39
+ return useAllSeriesOfType('pie');
42
40
  }
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createSeriesSelectorsOfType, createAllSeriesSelectorOfType } from "../internals/createSeriesSelectorOfType.js";
4
- const useSelectorSeries = createSeriesSelectorsOfType('radar');
5
- const useSelectorSeriesContext = createAllSeriesSelectorOfType('radar');
3
+ import { useSeriesOfType, useAllSeriesOfType } from "../internals/seriesSelectorOfType.js";
6
4
 
7
5
  /**
8
6
  * Get access to the internal state of radar series.
@@ -27,7 +25,7 @@ const useSelectorSeriesContext = createAllSeriesSelectorOfType('radar');
27
25
  */
28
26
 
29
27
  export function useRadarSeries(seriesIds) {
30
- return useSelectorSeries(seriesIds);
28
+ return useSeriesOfType('radar', seriesIds);
31
29
  }
32
30
 
33
31
  /**
@@ -38,5 +36,5 @@ export function useRadarSeries(seriesIds) {
38
36
  * @returns the radar series
39
37
  */
40
38
  export function useRadarSeriesContext() {
41
- return useSelectorSeriesContext();
39
+ return useAllSeriesOfType('radar');
42
40
  }
@@ -1,8 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { createSeriesSelectorsOfType, createAllSeriesSelectorOfType } from "../internals/createSeriesSelectorOfType.js";
4
- const useSelectorSeries = createSeriesSelectorsOfType('scatter');
5
- const useSelectorSeriesContext = createAllSeriesSelectorOfType('scatter');
3
+ import { useSeriesOfType, useAllSeriesOfType } from "../internals/seriesSelectorOfType.js";
6
4
 
7
5
  /**
8
6
  * Get access to the internal state of scatter series.
@@ -27,7 +25,7 @@ const useSelectorSeriesContext = createAllSeriesSelectorOfType('scatter');
27
25
  */
28
26
 
29
27
  export function useScatterSeries(seriesIds) {
30
- return useSelectorSeries(seriesIds);
28
+ return useSeriesOfType('scatter', seriesIds);
31
29
  }
32
30
 
33
31
  /**
@@ -38,5 +36,5 @@ export function useScatterSeries(seriesIds) {
38
36
  * @returns the scatter series
39
37
  */
40
38
  export function useScatterSeriesContext() {
41
- return useSelectorSeriesContext();
39
+ return useAllSeriesOfType('scatter');
42
40
  }
@@ -10,6 +10,9 @@ const offsetRatio = {
10
10
  end: 1,
11
11
  middle: 0.5
12
12
  };
13
+ function getTickPosition(scale, value, placement) {
14
+ return scale(value) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[placement] * scale.step();
15
+ }
13
16
  export function getTicks(options) {
14
17
  const {
15
18
  scale,
@@ -28,7 +31,13 @@ export function getTicks(options) {
28
31
  if (scale.bandwidth() > 0) {
29
32
  // scale type = 'band'
30
33
  const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain;
31
- return [...filteredDomain.map(value => {
34
+ const isReversed = scale.range()[0] > scale.range()[1];
35
+ // Indexes are inclusive regarding the entire band.
36
+ const startIndex = filteredDomain.findIndex(value => {
37
+ return isInside(getTickPosition(scale, value, isReversed ? 'start' : 'end'));
38
+ });
39
+ const endIndex = filteredDomain.findLastIndex(value => isInside(getTickPosition(scale, value, isReversed ? 'end' : 'start')));
40
+ return [...filteredDomain.slice(startIndex, endIndex + 1).map(value => {
32
41
  const defaultTickLabel = `${value}`;
33
42
  return {
34
43
  value,
@@ -38,10 +47,10 @@ export function getTicks(options) {
38
47
  tickNumber,
39
48
  defaultTickLabel
40
49
  }) ?? defaultTickLabel,
41
- offset: scale(value) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[tickPlacement] * scale.step(),
50
+ offset: getTickPosition(scale, value, tickPlacement),
42
51
  labelOffset: tickLabelPlacement === 'tick' ? 0 : scale.step() * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement])
43
52
  };
44
- }), ...(tickPlacement === 'extremities' ? [{
53
+ }), ...(tickPlacement === 'extremities' && endIndex === domain.length - 1 && isInside(scale.range()[1]) ? [{
45
54
  formattedValue: undefined,
46
55
  offset: scale.range()[1],
47
56
  labelOffset: 0
package/esm/index.d.ts CHANGED
@@ -29,4 +29,5 @@ export type { ChartContainerProps } from "./ChartContainer/index.js";
29
29
  export * from "./ChartDataProvider/index.js";
30
30
  export * from "./Toolbar/index.js";
31
31
  export * from "./ChartsWrapper/index.js";
32
- export * from "./ChartsBrushOverlay/index.js";
32
+ export * from "./ChartsBrushOverlay/index.js";
33
+ export * from "./utils/index.js";
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-charts v8.18.0
2
+ * @mui/x-charts v8.20.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -36,6 +36,7 @@ export * from "./ChartDataProvider/index.js";
36
36
  export * from "./Toolbar/index.js";
37
37
  export * from "./ChartsWrapper/index.js";
38
38
  export * from "./ChartsBrushOverlay/index.js";
39
+ export * from "./utils/index.js";
39
40
 
40
41
  // Locales should be imported from `@mui/x-charts/locales`
41
42
  // export * from './locales';
@@ -86,11 +86,7 @@ export const getStringSize = (text, style = {}) => {
86
86
  });
87
87
  measurementElem.textContent = str;
88
88
  measurementSpanContainer.replaceChildren(measurementElem);
89
- const rect = measurementElem.getBoundingClientRect();
90
- const result = {
91
- width: rect.width,
92
- height: rect.height
93
- };
89
+ const result = measureSVGTextElement(measurementElem);
94
90
  stringCache.set(cacheKey, result);
95
91
  if (stringCache.size + 1 > MAX_CACHE_NUM) {
96
92
  stringCache.clear();
@@ -134,21 +130,17 @@ export function batchMeasureStrings(texts, style = {}) {
134
130
  measurementContainer.style[camelCaseToDashCase(styleKey)] = convertPixelValue(styleKey, measurementSpanStyle[styleKey]);
135
131
  return styleKey;
136
132
  });
137
- const measurementElems = [];
133
+ const measurementElements = [];
138
134
  for (const string of textToMeasure) {
139
135
  const measurementElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');
140
136
  measurementElem.textContent = `${string}`;
141
- measurementElems.push(measurementElem);
137
+ measurementElements.push(measurementElem);
142
138
  }
143
- measurementContainer.replaceChildren(...measurementElems);
139
+ measurementContainer.replaceChildren(...measurementElements);
144
140
  for (let i = 0; i < textToMeasure.length; i += 1) {
145
141
  const text = textToMeasure[i];
146
- const measurementSpan = measurementContainer.children[i];
147
- const rect = measurementSpan.getBoundingClientRect();
148
- const result = {
149
- width: rect.width,
150
- height: rect.height
151
- };
142
+ const measurementElem = measurementContainer.children[i];
143
+ const result = measureSVGTextElement(measurementElem);
152
144
  const cacheKey = `${text}-${styleString}`;
153
145
  stringCache.set(cacheKey, result);
154
146
  sizeMap.set(text, result);
@@ -162,6 +154,30 @@ export function batchMeasureStrings(texts, style = {}) {
162
154
  }
163
155
  return sizeMap;
164
156
  }
157
+
158
+ /**
159
+ * Measures an SVG text element using getBBox() with fallback to getBoundingClientRect()
160
+ * @param element SVG text element to measure
161
+ * @returns width and height of the text element
162
+ */
163
+ function measureSVGTextElement(element) {
164
+ // getBBox() is more reliable across browsers for SVG elements
165
+ try {
166
+ const result = element.getBBox();
167
+ return {
168
+ width: result.width,
169
+ height: result.height
170
+ };
171
+ } catch {
172
+ // Fallback to getBoundingClientRect if getBBox fails
173
+ // This can happen in tests
174
+ const result = element.getBoundingClientRect();
175
+ return {
176
+ width: result.width,
177
+ height: result.height
178
+ };
179
+ }
180
+ }
165
181
  let measurementContainer = null;
166
182
 
167
183
  /**
@@ -1,2 +1,3 @@
1
+ import { NumberValue } from '@mui/x-charts-vendor/d3-scale';
1
2
  import { ContinuousScaleName, D3ContinuousScale } from "../models/axis.js";
2
- export declare function getScale(scaleType: ContinuousScaleName, domain: readonly any[], range: readonly any[]): D3ContinuousScale;
3
+ export declare function getScale<Domain extends NumberValue = any, Range = any>(scaleType: ContinuousScaleName, domain: Iterable<Domain>, range: readonly Range[]): D3ContinuousScale<Range, Range>;
@@ -15,7 +15,7 @@ export { useBarPlotData } from "../BarChart/useBarPlotData.js";
15
15
  export { useRadarChartProps } from "../RadarChart/useRadarChartProps.js";
16
16
  export * from "../ChartContainer/useChartContainerProps.js";
17
17
  export * from "../ChartDataProvider/useChartDataProviderProps.js";
18
- export * from "./createSeriesSelectorOfType.js";
18
+ export * from "./seriesSelectorOfType.js";
19
19
  export * from "./plugins/corePlugins/useChartId/index.js";
20
20
  export * from "./plugins/corePlugins/useChartSeries/index.js";
21
21
  export * from "./plugins/corePlugins/useChartDimensions/index.js";
@@ -18,7 +18,7 @@ export { useBarPlotData } from "../BarChart/useBarPlotData.js";
18
18
  export { useRadarChartProps } from "../RadarChart/useRadarChartProps.js";
19
19
  export * from "../ChartContainer/useChartContainerProps.js";
20
20
  export * from "../ChartDataProvider/useChartDataProviderProps.js";
21
- export * from "./createSeriesSelectorOfType.js";
21
+ export * from "./seriesSelectorOfType.js";
22
22
 
23
23
  // plugins
24
24
  export * from "./plugins/corePlugins/useChartId/index.js";
@@ -1,3 +1,3 @@
1
- import { createSelector } from "../../utils/selectors.js";
1
+ import { createSelector } from '@mui/x-internals/store';
2
2
  const selectorChartAnimationState = state => state.animation;
3
- export const selectorChartSkipAnimation = createSelector([selectorChartAnimationState], state => state.skip || state.skipAnimationRequests > 0);
3
+ export const selectorChartSkipAnimation = createSelector(selectorChartAnimationState, state => state.skip || state.skipAnimationRequests > 0);
@@ -1,5 +1,4 @@
1
- import { createSelectorMemoized } from '@mui/x-internals/store';
2
- import { createSelector } from "../../utils/selectors.js";
1
+ import { createSelector, createSelectorMemoized } from '@mui/x-internals/store';
3
2
  import { selectorChartAxisSizes } from "../../featurePlugins/useChartCartesianAxis/useChartAxisSize.selectors.js";
4
3
  export const selectorChartDimensionsState = state => state.dimensions;
5
4
  export const selectorChartMargin = state => state.dimensions.margin;
@@ -26,7 +25,7 @@ export const selectorChartDrawingArea = createSelectorMemoized(selectorChartDime
26
25
  bottom: marginBottom + axisSizeBottom
27
26
  };
28
27
  });
29
- export const selectorChartSvgWidth = createSelector([selectorChartDimensionsState], dimensionsState => dimensionsState.width);
30
- export const selectorChartSvgHeight = createSelector([selectorChartDimensionsState], dimensionsState => dimensionsState.height);
31
- export const selectorChartPropsWidth = createSelector([selectorChartDimensionsState], dimensionsState => dimensionsState.propsWidth);
32
- export const selectorChartPropsHeight = createSelector([selectorChartDimensionsState], dimensionsState => dimensionsState.propsHeight);
28
+ export const selectorChartSvgWidth = createSelector(selectorChartDimensionsState, dimensionsState => dimensionsState.width);
29
+ export const selectorChartSvgHeight = createSelector(selectorChartDimensionsState, dimensionsState => dimensionsState.height);
30
+ export const selectorChartPropsWidth = createSelector(selectorChartDimensionsState, dimensionsState => dimensionsState.propsWidth);
31
+ export const selectorChartPropsHeight = createSelector(selectorChartDimensionsState, dimensionsState => dimensionsState.propsHeight);
@@ -1,3 +1,3 @@
1
- import { createSelector } from "../../utils/selectors.js";
1
+ import { createSelector } from '@mui/x-internals/store';
2
2
  export const selectorChartExperimentalFeaturesState = state => state.experimentalFeatures;
3
- export const selectorPreferStrictDomainInLineCharts = createSelector([selectorChartExperimentalFeaturesState], features => Boolean(features?.preferStrictDomainInLineCharts));
3
+ export const selectorPreferStrictDomainInLineCharts = createSelector(selectorChartExperimentalFeaturesState, features => Boolean(features?.preferStrictDomainInLineCharts));
@@ -1,4 +1,4 @@
1
- import { createSelector } from "../../utils/selectors.js";
1
+ import { createSelector } from '@mui/x-internals/store';
2
2
  const selectorChartIdState = state => state.id;
3
3
 
4
4
  /**
@@ -6,4 +6,4 @@ const selectorChartIdState = state => state.id;
6
6
  * @param {ChartState<[UseChartIdSignature]>} state The state of the chart.
7
7
  * @returns {string} The id attribute of the chart.
8
8
  */
9
- export const selectorChartId = createSelector([selectorChartIdState], idState => idState.chartId);
9
+ export const selectorChartId = createSelector(selectorChartIdState, idState => idState.chartId);
@@ -44,6 +44,9 @@ export const useChartInteractionListener = ({
44
44
  name: 'zoomTurnWheel',
45
45
  sensitivity: 0.01,
46
46
  initialDelta: 1
47
+ }), new TurnWheelGesture({
48
+ name: 'panTurnWheel',
49
+ sensitivity: 0.5
47
50
  }), new TapAndDragGesture({
48
51
  name: 'zoomTapAndDrag',
49
52
  dragThreshold: 10
@@ -63,7 +66,7 @@ export const useChartInteractionListener = ({
63
66
  if (!svg || !gestureManager) {
64
67
  return undefined;
65
68
  }
66
- gestureManager.registerElement(['pan', 'move', 'zoomPinch', 'zoomPan', 'zoomTurnWheel', 'tap', 'quickPress', 'zoomTapAndDrag', 'zoomPressAndDrag', 'zoomDoubleTapReset', 'brush'], svg);
69
+ gestureManager.registerElement(['pan', 'move', 'zoomPinch', 'zoomPan', 'zoomTurnWheel', 'panTurnWheel', 'tap', 'quickPress', 'zoomTapAndDrag', 'zoomPressAndDrag', 'zoomDoubleTapReset', 'brush'], svg);
67
70
  return () => {
68
71
  // Cleanup gesture manager
69
72
  gestureManager.unregisterAllGestures(svg);
@@ -1,6 +1,6 @@
1
1
  import { MoveEvent, PanEvent, PanGestureOptions, PinchEvent, PinchGestureOptions, PressEvent, TapEvent, TurnWheelEvent, type PressAndDragEvent, type PressAndDragGestureOptions, type TapAndDragEvent, type TapAndDragGestureOptions, type TapGestureOptions, type TurnWheelGestureOptions } from '@mui/x-internal-gestures/core';
2
2
  import { ChartPluginSignature } from "../../models/index.js";
3
- export type ChartInteraction = 'pan' | 'panStart' | 'panEnd' | 'zoomPan' | 'zoomPanStart' | 'zoomPanEnd' | 'zoomPinch' | 'zoomPinchStart' | 'zoomPinchEnd' | 'zoomTurnWheel' | 'zoomTapAndDrag' | 'zoomTapAndDragStart' | 'zoomTapAndDragEnd' | 'zoomPressAndDrag' | 'zoomPressAndDragStart' | 'zoomPressAndDragEnd' | 'move' | 'moveStart' | 'moveEnd' | 'tap' | 'quickPress' | 'quickPressEnd' | 'zoomDoubleTapReset' | 'brush' | 'brushStart' | 'brushCancel' | 'brushEnd';
3
+ export type ChartInteraction = 'pan' | 'panStart' | 'panEnd' | 'zoomPan' | 'zoomPanStart' | 'zoomPanEnd' | 'zoomPinch' | 'zoomPinchStart' | 'zoomPinchEnd' | 'zoomTurnWheel' | 'panTurnWheel' | 'zoomTapAndDrag' | 'zoomTapAndDragStart' | 'zoomTapAndDragEnd' | 'zoomPressAndDrag' | 'zoomPressAndDragStart' | 'zoomPressAndDragEnd' | 'move' | 'moveStart' | 'moveEnd' | 'tap' | 'quickPress' | 'quickPressEnd' | 'zoomDoubleTapReset' | 'brush' | 'brushStart' | 'brushCancel' | 'brushEnd';
4
4
  export type InteractionListenerResult = {
5
5
  cleanup: () => void;
6
6
  };
@@ -8,6 +8,7 @@ export type AddInteractionListener = {
8
8
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'pan' | 'panStart' | 'panEnd' | 'zoomPan' | 'zoomPanStart' | 'zoomPanEnd' | 'brush' | 'brushStart' | 'brushCancel' | 'brushEnd', callback: (event: PanEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
9
9
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'zoomPinch' | 'zoomPinchStart' | 'zoomPinchEnd', callback: (event: PinchEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
10
10
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'zoomTurnWheel', callback: (event: TurnWheelEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
11
+ <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'panTurnWheel', callback: (event: TurnWheelEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
11
12
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'move' | 'moveStart' | 'moveEnd', callback: (event: MoveEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
12
13
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'tap' | 'zoomDoubleTapReset', callback: (event: TapEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
13
14
  <CustomData extends Record<string, unknown> = Record<string, unknown>>(interaction: 'quickPress' | 'quickPressEnd', callback: (event: PressEvent<CustomData>) => void, options?: boolean | AddEventListenerOptions): InteractionListenerResult;
@@ -18,6 +19,7 @@ export type UpdateZoomInteractionListeners = {
18
19
  (interaction: 'zoomPan', options?: Omit<PanGestureOptions<'zoomPan'>, 'name'>): void;
19
20
  (interaction: 'zoomPinch', options?: Omit<PinchGestureOptions<'zoomPinch'>, 'name'>): void;
20
21
  (interaction: 'zoomTurnWheel', options?: Omit<TurnWheelGestureOptions<'zoomTurnWheel'>, 'name'>): void;
22
+ (interaction: 'panTurnWheel', options?: Omit<TurnWheelGestureOptions<'panTurnWheel'>, 'name'>): void;
21
23
  (interaction: 'zoomTapAndDrag', options?: Omit<TapAndDragGestureOptions<'zoomTapAndDrag'>, 'name'>): void;
22
24
  (interaction: 'zoomPressAndDrag', options?: Omit<PressAndDragGestureOptions<'zoomPressAndDrag'>, 'name'>): void;
23
25
  (interaction: 'zoomDoubleTapReset', options?: Omit<TapGestureOptions<'zoomDoubleTapReset'>, 'name'>): void;
@@ -1,23 +1,29 @@
1
1
  import { AllSeriesType } from "../../../../models/seriesType/index.js";
2
2
  import { ChartSeriesType, DatasetType } from "../../../../models/seriesType/config.js";
3
3
  import { ChartSeriesConfig } from "../../models/seriesConfig/index.js";
4
- import { SeriesProcessorResult } from "../../models/seriesConfig/seriesProcessor.types.js";
4
+ import { DefaultizedSeriesGroups, ProcessedSeries } from "./useChartSeries.types.js";
5
5
  /**
6
- * This methods is the interface between what the developer is providing and what components receives
7
- * To simplify the components behaviors, it groups series by type, such that LinePlots props are not updated if some line data are modified
8
- * It also add defaultized values such as the ids, colors
6
+ * This method groups series by type and adds defaultized values such as the ids and colors.
7
+ * It does NOT apply the series processors - that happens in a selector.
9
8
  * @param series The array of series provided by the developer
10
9
  * @param colors The color palette used to defaultize series colors
11
- * @returns An object structuring all the series by type.
10
+ * @returns An object structuring all the series by type with default values.
12
11
  */
13
- export declare const preprocessSeries: <TSeriesType extends ChartSeriesType>({
12
+ export declare const defaultizeSeries: <TSeriesType extends ChartSeriesType>({
14
13
  series,
15
14
  colors,
16
- seriesConfig,
17
- dataset
15
+ seriesConfig
18
16
  }: {
19
17
  series: Readonly<AllSeriesType<TSeriesType>[]>;
20
18
  colors: readonly string[];
21
19
  seriesConfig: ChartSeriesConfig<TSeriesType>;
22
- dataset?: Readonly<DatasetType>;
23
- }) => { [type in TSeriesType]?: SeriesProcessorResult<TSeriesType> | undefined };
20
+ }) => DefaultizedSeriesGroups<TSeriesType>;
21
+ /**
22
+ * Applies series processors to the defaultized series groups.
23
+ * This should be called in a selector to compute processed series on-demand.
24
+ * @param defaultizedSeries The defaultized series groups
25
+ * @param seriesConfig The series configuration
26
+ * @param dataset The optional dataset
27
+ * @returns Processed series with all transformations applied
28
+ */
29
+ export declare const applySeriesProcessors: <TSeriesType extends ChartSeriesType>(defaultizedSeries: DefaultizedSeriesGroups<TSeriesType>, seriesConfig: ChartSeriesConfig<TSeriesType>, dataset?: Readonly<DatasetType>) => ProcessedSeries<TSeriesType>;
@@ -1,22 +1,17 @@
1
1
  /**
2
- * This methods is the interface between what the developer is providing and what components receives
3
- * To simplify the components behaviors, it groups series by type, such that LinePlots props are not updated if some line data are modified
4
- * It also add defaultized values such as the ids, colors
2
+ * This method groups series by type and adds defaultized values such as the ids and colors.
3
+ * It does NOT apply the series processors - that happens in a selector.
5
4
  * @param series The array of series provided by the developer
6
5
  * @param colors The color palette used to defaultize series colors
7
- * @returns An object structuring all the series by type.
6
+ * @returns An object structuring all the series by type with default values.
8
7
  */
9
- export const preprocessSeries = ({
8
+ export const defaultizeSeries = ({
10
9
  series,
11
10
  colors,
12
- seriesConfig,
13
- dataset
11
+ seriesConfig
14
12
  }) => {
15
13
  // Group series by type
16
14
  const seriesGroups = {};
17
- // Notice the line about uses `ChartSeriesType` instead of TSeriesType.
18
- // That's probably because the series.type is not propagated from the generic but hardcoded in the config.
19
-
20
15
  series.forEach((seriesData, seriesIndex) => {
21
16
  const seriesWithDefaultValues = seriesConfig[seriesData.type].getSeriesWithDefaultValues(seriesData, seriesIndex, colors);
22
17
  const id = seriesWithDefaultValues.id;
@@ -32,12 +27,25 @@ export const preprocessSeries = ({
32
27
  seriesGroups[seriesData.type].series[id] = seriesWithDefaultValues;
33
28
  seriesGroups[seriesData.type].seriesOrder.push(id);
34
29
  });
30
+ return seriesGroups;
31
+ };
32
+
33
+ /**
34
+ * Applies series processors to the defaultized series groups.
35
+ * This should be called in a selector to compute processed series on-demand.
36
+ * @param defaultizedSeries The defaultized series groups
37
+ * @param seriesConfig The series configuration
38
+ * @param dataset The optional dataset
39
+ * @returns Processed series with all transformations applied
40
+ */
41
+ export const applySeriesProcessors = (defaultizedSeries, seriesConfig, dataset) => {
35
42
  const processedSeries = {};
43
+
36
44
  // Apply formatter on a type group
37
45
  Object.keys(seriesConfig).forEach(type => {
38
- const group = seriesGroups[type];
46
+ const group = defaultizedSeries[type];
39
47
  if (group !== undefined) {
40
- processedSeries[type] = seriesConfig[type]?.seriesProcessor?.(group, dataset) ?? seriesGroups[type];
48
+ processedSeries[type] = seriesConfig[type]?.seriesProcessor?.(group, dataset) ?? group;
41
49
  }
42
50
  });
43
51
  return processedSeries;
@@ -3,7 +3,7 @@
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
5
  import { rainbowSurgePalette } from "../../../../colorPalettes/index.js";
6
- import { preprocessSeries } from "./processSeries.js";
6
+ import { defaultizeSeries } from "./processSeries.js";
7
7
  export const useChartSeries = ({
8
8
  params,
9
9
  store,
@@ -25,11 +25,10 @@ export const useChartSeries = ({
25
25
  return;
26
26
  }
27
27
  store.set('series', _extends({}, store.state.series, {
28
- processedSeries: preprocessSeries({
28
+ defaultizedSeries: defaultizeSeries({
29
29
  series,
30
30
  colors: typeof colors === 'function' ? colors(theme) : colors,
31
- seriesConfig,
32
- dataset
31
+ seriesConfig
33
32
  }),
34
33
  dataset
35
34
  }));
@@ -59,11 +58,10 @@ useChartSeries.getInitialState = ({
59
58
  return {
60
59
  series: {
61
60
  seriesConfig,
62
- processedSeries: preprocessSeries({
61
+ defaultizedSeries: defaultizeSeries({
63
62
  series,
64
63
  colors: typeof colors === 'function' ? colors(theme) : colors,
65
- seriesConfig,
66
- dataset
64
+ seriesConfig
67
65
  }),
68
66
  dataset
69
67
  }