@mui/x-charts 8.12.0 → 8.13.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 (52) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/ChartsSurface/ChartsSurface.js +4 -3
  3. package/PieChart/PieArc.d.ts +3 -0
  4. package/PieChart/PieArc.js +13 -12
  5. package/PieChart/PieArcPlot.js +27 -3
  6. package/esm/ChartsSurface/ChartsSurface.js +4 -3
  7. package/esm/PieChart/PieArc.d.ts +3 -0
  8. package/esm/PieChart/PieArc.js +14 -13
  9. package/esm/PieChart/PieArcPlot.js +29 -5
  10. package/esm/index.js +1 -1
  11. package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +60 -32
  12. package/esm/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +19 -5
  13. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisScale.d.ts +5 -2
  14. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisScale.js +8 -10
  15. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisPreview.selectors.js +7 -5
  16. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.ts +10 -0
  17. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.js +13 -4
  18. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.d.ts +2 -2
  19. package/esm/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +30 -7
  20. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.js +6 -4
  21. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.d.ts +6 -1
  22. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.js +2 -1
  23. package/esm/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.types.d.ts +6 -0
  24. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js +115 -155
  25. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.d.ts +14 -2
  26. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.js +27 -1
  27. package/esm/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.types.d.ts +2 -0
  28. package/esm/internals/plugins/featurePlugins/useChartPolarAxis/computeAxisValue.js +2 -5
  29. package/esm/internals/ticks.d.ts +3 -5
  30. package/esm/internals/ticks.js +6 -5
  31. package/index.js +1 -1
  32. package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.js +59 -31
  33. package/internals/plugins/corePlugins/useChartInteractionListener/useChartInteractionListener.types.d.ts +19 -5
  34. package/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisScale.d.ts +5 -2
  35. package/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisScale.js +8 -11
  36. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisPreview.selectors.js +6 -4
  37. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.ts +10 -0
  38. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.js +14 -5
  39. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.d.ts +2 -2
  40. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianHighlight.selectors.js +30 -7
  41. package/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.js +6 -4
  42. package/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.d.ts +6 -1
  43. package/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.selectors.js +3 -2
  44. package/internals/plugins/featurePlugins/useChartInteraction/useChartInteraction.types.d.ts +6 -0
  45. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.js +115 -155
  46. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.d.ts +14 -2
  47. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.selectors.js +28 -2
  48. package/internals/plugins/featurePlugins/useChartKeyboardNavigation/useChartKeyboardNavigation.types.d.ts +2 -0
  49. package/internals/plugins/featurePlugins/useChartPolarAxis/computeAxisValue.js +1 -4
  50. package/internals/ticks.d.ts +3 -5
  51. package/internals/ticks.js +7 -5
  52. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -5,6 +5,151 @@
5
5
  All notable changes to this project will be documented in this file.
6
6
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
7
7
 
8
+ ## 8.13.0
9
+
10
+ _Oct 1, 2025_
11
+
12
+ We'd like to extend a big thank you to the 14 contributors who made this release possible. Here are some highlights ✨:
13
+
14
+ - 📊 The chart zoom now supports the `tapAndDrag` gesture. Zoom in/out by tapping twice and dragging vertically.
15
+ - 🔎 Charts now allow [fine-grained control for zoom interactions](https://mui.com/x/react-charts/zoom-and-pan/#zoom-interactions-configuration).
16
+ ```jsx
17
+ <BarChartPro
18
+ zoomInteractionConfig={{
19
+ // Only zoom when Control key is pressed
20
+ zoom: [{ type: 'wheel', keys: ['Control'] }],
21
+ // Only pan when Shift key is pressed
22
+ pan: [{ type: 'drag', keys: ['Shift'] }],
23
+ }}
24
+ />
25
+ ```
26
+ - ➡️ Data Grid grouping rows now persist their expansion state when the rows are updated.
27
+ - 📜 Updated Data Grid vertical scrollbar to include pinned rows and aggregation sections.
28
+ - 📌 Improved the appearance of [pinned columns](https://mui.com/x/react-data-grid/column-pinning/#pinned-columns-appearance) and [pinned rows](https://mui.com/x/react-data-grid/row-pinning/#pinned-rows-appearance) sections in the Data Grid.
29
+ - 🚀 Tree View now fetches the children of expanded items on mount when using lazy loading.
30
+ - 🐞 Bugfixes
31
+ - 📚 Documentation improvements
32
+
33
+ Special thanks go out to the community members for their valuable contributions:
34
+ @sai6855
35
+
36
+ The following are all team members who have contributed to this release:
37
+ @alexfauquette, @arminmeh, @bernardobelchior, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @KenanYusuf, @mapache-salvaje, @MBilalShafi, @mnajdova, @rita-codes, @siriwatknp
38
+
39
+ ### Data Grid
40
+
41
+ #### `@mui/x-data-grid@8.13.0`
42
+
43
+ - [DataGrid] Add scroll shadows and fix scrollbar overlap (#16476) @KenanYusuf
44
+ - [DataGrid] Fix row spanning stale state issue (#19733) @MBilalShafi
45
+ - [DataGrid] Fix toolbar `slotProps` not being applied (#19769) @sai6855
46
+ - [DataGrid] Skip calling `fetchRows()` when strategy is not initialized (#19728) @MBilalShafi
47
+
48
+ #### `@mui/x-data-grid-pro@8.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
49
+
50
+ Same changes as in `@mui/x-data-grid@8.13.0`, plus:
51
+
52
+ - [DataGridPro] Retain expansion state on rows update (#19697) @MBilalShafi
53
+
54
+ #### `@mui/x-data-grid-premium@8.13.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
55
+
56
+ Same changes as in `@mui/x-data-grid-pro@8.13.0`, plus:
57
+
58
+ - [DataGridPremium] Add `metadata.referenceId` to AI assistant prompt resolver (#19695) @hasdfa
59
+ - [DataGridPremium] Fix aggregation value retrieval (#19724) @arminmeh
60
+ - [DataGridPremium] Get correct active chart id while rebuilding data (#19720) @arminmeh
61
+
62
+ ### Date and Time Pickers
63
+
64
+ #### `@mui/x-date-pickers@8.12.0`
65
+
66
+ Internal changes.
67
+
68
+ #### `@mui/x-date-pickers-pro@8.12.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
69
+
70
+ Same changes as in `@mui/x-date-pickers@8.12.0`.
71
+
72
+ ### Charts
73
+
74
+ #### `@mui/x-charts@8.13.0`
75
+
76
+ - [charts] Add `tapAndDrag` zoom gesture (#19727) @JCQuintas
77
+ - [charts] Add arc focus indicator that follows the arc form (#19696) @mnajdova
78
+ - [charts] Fix outline color (#19752) @alexfauquette
79
+ - [charts] Improve tooltip doc (#19731) @JCQuintas
80
+ - [charts] Make axis highlight reflect the keyboard interaction (#19631) @alexfauquette
81
+ - [charts] Prevent horizontal scroll on keyboard navigation (#19704) @alexfauquette
82
+ - [charts] Simplify gestures by removing bindings (#19767) @JCQuintas
83
+
84
+ #### `@mui/x-charts-pro@8.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
85
+
86
+ Same changes as in `@mui/x-charts@8.13.0`, plus:
87
+
88
+ - [charts-pro] Allow zoom interactions to be configured (#18646) @JCQuintas
89
+ - [charts-pro] Fix zoom preview having wrong domain in some cases (#19723) @bernardobelchior
90
+
91
+ #### `@mui/x-charts-premium@8.13.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
92
+
93
+ Same changes as in `@mui/x-charts-pro@8.13.0`.
94
+
95
+ ### Tree View
96
+
97
+ #### `@mui/x-tree-view@8.13.0`
98
+
99
+ - [tree view] Export the `apiRef` type of each Tree View component (#19543) @flaviendelangle
100
+ - [tree view] Fix indeterminate checkbox state (#19544) @flaviendelangle
101
+ - [tree view] Improve the lazy loading initial expansion (#19284) @flaviendelangle
102
+ - [tree view] Use Base UI utils whenever possible (#19502) @flaviendelangle
103
+
104
+ #### `@mui/x-tree-view-pro@8.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
105
+
106
+ Same changes as in `@mui/x-tree-view@8.13.0`.
107
+
108
+ ### Codemod
109
+
110
+ #### `@mui/x-codemod@8.12.0`
111
+
112
+ Internal changes.
113
+
114
+ ### Docs
115
+
116
+ - [docs] Add a recipe to customize editing component with Autocomplete (#19651) @siriwatknp
117
+ - [docs] Refine the electricity scatter tooltip (#19689) @alexfauquette
118
+ - [docs] Revise the Axis doc (#19052) @mapache-salvaje
119
+ - [docs] Remove reference to nonexistent `FocusedMark` API page (#19773) @bernardobelchior
120
+
121
+ ### Core
122
+
123
+ - [code-infra] Change charts codspeed integration to use walltime (#19729) @JCQuintas
124
+ - [code-infra] Port stylelint from core repo (#19633) @Janpot
125
+ - [code-infra] Stabilize fake timers in regression tests (#19719) @Janpot
126
+ - [code-infra] Stabilize size for bundles with `releaseInfo` (#19674) @Janpot
127
+ - [code-infra] Fix `pnpm-lock.yaml` broken lockfile (#19755) @bernardobelchior
128
+
129
+ ## 8.12.1
130
+
131
+ _Sep 25, 2025_
132
+
133
+ Release highlight ✨:
134
+
135
+ - 🐞 Hotfix for Grid-Charts integration issue with aggregated values
136
+
137
+ ### Data Grid
138
+
139
+ #### `@mui/x-data-grid@8.12.1`
140
+
141
+ Internal changes.
142
+
143
+ #### `@mui/x-data-grid-pro@8.12.1` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
144
+
145
+ Same changes as in `@mui/x-data-grid@8.12.1`.
146
+
147
+ #### `@mui/x-data-grid-premium@8.12.1` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
148
+
149
+ Same changes as in `@mui/x-data-grid-pro@8.12.1`, plus:
150
+
151
+ - [DataGridPremium] Collect aggregated values properly for the charts integration context (#19714) @arminmeh
152
+
8
153
  ## 8.12.0
9
154
 
10
155
  _Sep 25, 2025_
@@ -25,7 +25,8 @@ const ChartsSurfaceStyles = (0, _styles.styled)('svg', {
25
25
  name: 'MuiChartsSurface',
26
26
  slot: 'Root'
27
27
  })(({
28
- ownerState
28
+ ownerState,
29
+ theme
29
30
  }) => ({
30
31
  width: ownerState.width ?? '100%',
31
32
  height: ownerState.height ?? '100%',
@@ -45,14 +46,14 @@ const ChartsSurfaceStyles = (0, _styles.styled)('svg', {
45
46
  },
46
47
  '&:focus-visible': {
47
48
  // Show focus outline on the SVG container only when using keyboard navigation
48
- outline: 'auto',
49
+ outline: `${(theme.vars ?? theme).palette.text.primary} solid 2px`,
49
50
  '&[data-has-focused-item=true]': {
50
51
  // But not if the chart has a focused children item
51
52
  outline: 'none'
52
53
  }
53
54
  },
54
55
  '& [data-focused=true]': {
55
- outline: 'auto'
56
+ outline: `${(theme.vars ?? theme).palette.text.primary} solid 2px`
56
57
  }
57
58
  }));
58
59
 
@@ -12,6 +12,8 @@ export interface PieArcClasses {
12
12
  * Needs to be suffixed with the series ID: `.${pieArcClasses.series}-${seriesId}`.
13
13
  */
14
14
  series: string;
15
+ /** Styles applied to the focus indicator element. */
16
+ focusIndicator: string;
15
17
  }
16
18
  export type PieArcClassKey = keyof PieArcClasses;
17
19
  interface PieArcOwnerState {
@@ -21,6 +23,7 @@ interface PieArcOwnerState {
21
23
  isFaded: boolean;
22
24
  isHighlighted: boolean;
23
25
  isFocused: boolean;
26
+ stroke?: string;
24
27
  classes?: Partial<PieArcClasses>;
25
28
  }
26
29
  export declare function getPieArcUtilityClass(slot: string): string;
@@ -13,6 +13,7 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
13
13
  var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
14
14
  var React = _interopRequireWildcard(require("react"));
15
15
  var _propTypes = _interopRequireDefault(require("prop-types"));
16
+ var _clsx = _interopRequireDefault(require("clsx"));
16
17
  var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
17
18
  var _generateUtilityClass = _interopRequireDefault(require("@mui/utils/generateUtilityClass"));
18
19
  var _styles = require("@mui/material/styles");
@@ -21,11 +22,11 @@ var _hooks = require("../hooks");
21
22
  var _animation = require("../internals/animation/animation");
22
23
  var _useInteractionItemProps = require("../hooks/useInteractionItemProps");
23
24
  var _jsxRuntime = require("react/jsx-runtime");
24
- const _excluded = ["classes", "color", "dataIndex", "id", "isFaded", "isHighlighted", "isFocused", "onClick", "cornerRadius", "startAngle", "endAngle", "innerRadius", "outerRadius", "paddingAngle", "skipAnimation"];
25
+ const _excluded = ["className", "classes", "color", "dataIndex", "id", "isFaded", "isHighlighted", "isFocused", "onClick", "cornerRadius", "startAngle", "endAngle", "innerRadius", "outerRadius", "paddingAngle", "skipAnimation", "stroke"];
25
26
  function getPieArcUtilityClass(slot) {
26
27
  return (0, _generateUtilityClass.default)('MuiPieArc', slot);
27
28
  }
28
- const pieArcClasses = exports.pieArcClasses = (0, _generateUtilityClasses.default)('MuiPieArc', ['root', 'highlighted', 'faded', 'series']);
29
+ const pieArcClasses = exports.pieArcClasses = (0, _generateUtilityClasses.default)('MuiPieArc', ['root', 'highlighted', 'faded', 'series', 'focusIndicator']);
29
30
  const useUtilityClasses = ownerState => {
30
31
  const {
31
32
  classes,
@@ -43,17 +44,14 @@ const PieArcRoot = (0, _styles.styled)('path', {
43
44
  name: 'MuiPieArc',
44
45
  slot: 'Root',
45
46
  overridesResolver: (_, styles) => styles.arc // FIXME: Inconsistent naming with slot
46
- })(({
47
- theme
48
- }) => ({
49
- // Got to move stroke to an element prop instead of style.
50
- stroke: (theme.vars || theme).palette.background.paper,
47
+ })({
51
48
  transitionProperty: 'opacity, fill, filter',
52
49
  transitionDuration: `${_animation.ANIMATION_DURATION_MS}ms`,
53
50
  transitionTimingFunction: _animation.ANIMATION_TIMING_FUNCTION
54
- }));
51
+ });
55
52
  const PieArc = exports.PieArc = /*#__PURE__*/React.forwardRef(function PieArc(props, ref) {
56
53
  const {
54
+ className,
57
55
  classes: innerClasses,
58
56
  color,
59
57
  dataIndex,
@@ -68,9 +66,12 @@ const PieArc = exports.PieArc = /*#__PURE__*/React.forwardRef(function PieArc(pr
68
66
  innerRadius,
69
67
  outerRadius,
70
68
  paddingAngle,
71
- skipAnimation
69
+ skipAnimation,
70
+ stroke: strokeProp
72
71
  } = props,
73
72
  other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
73
+ const theme = (0, _styles.useTheme)();
74
+ const stroke = strokeProp ?? (theme.vars || theme).palette.background.paper;
74
75
  const ownerState = {
75
76
  id,
76
77
  dataIndex,
@@ -100,15 +101,15 @@ const PieArc = exports.PieArc = /*#__PURE__*/React.forwardRef(function PieArc(pr
100
101
  onClick: onClick,
101
102
  cursor: onClick ? 'pointer' : 'unset',
102
103
  ownerState: ownerState,
103
- className: classes.root,
104
+ className: (0, _clsx.default)(classes.root, className),
104
105
  fill: ownerState.color,
105
106
  opacity: ownerState.isFaded ? 0.3 : 1,
106
107
  filter: ownerState.isHighlighted ? 'brightness(120%)' : 'none',
108
+ stroke: stroke,
107
109
  strokeWidth: 1,
108
110
  strokeLinejoin: "round",
109
111
  "data-highlighted": ownerState.isHighlighted || undefined,
110
- "data-faded": ownerState.isFaded || undefined,
111
- "data-focused": isFocused || undefined
112
+ "data-faded": ownerState.isFaded || undefined
112
113
  }, other, interactionProps, animatedProps));
113
114
  });
114
115
  if (process.env.NODE_ENV !== "production") PieArc.displayName = "PieArc";
@@ -11,6 +11,8 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
11
11
  var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
12
12
  var React = _interopRequireWildcard(require("react"));
13
13
  var _propTypes = _interopRequireDefault(require("prop-types"));
14
+ var _styles = require("@mui/material/styles");
15
+ var _useFocusedItem = require("../hooks/useFocusedItem");
14
16
  var _PieArc = require("./PieArc");
15
17
  var _useTransformData = require("./dataTransform/useTransformData");
16
18
  var _jsxRuntime = require("react/jsx-runtime");
@@ -33,6 +35,7 @@ function PieArcPlot(props) {
33
35
  skipAnimation
34
36
  } = props,
35
37
  other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
38
+ const theme = (0, _styles.useTheme)();
36
39
  const transformedData = (0, _useTransformData.useTransformData)({
37
40
  innerRadius,
38
41
  outerRadius,
@@ -43,12 +46,16 @@ function PieArcPlot(props) {
43
46
  faded,
44
47
  data
45
48
  });
49
+ const {
50
+ dataIndex: focusedIndex = -1
51
+ } = (0, _useFocusedItem.useFocusedItem)() ?? {};
52
+ const focusedItem = focusedIndex !== -1 ? transformedData[focusedIndex] : null;
46
53
  if (data.length === 0) {
47
54
  return null;
48
55
  }
49
56
  const Arc = slots?.pieArc ?? _PieArc.PieArc;
50
- return /*#__PURE__*/(0, _jsxRuntime.jsx)("g", (0, _extends2.default)({}, other, {
51
- children: transformedData.map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Arc, (0, _extends2.default)({
57
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("g", (0, _extends2.default)({}, other, {
58
+ children: [transformedData.map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Arc, (0, _extends2.default)({
52
59
  startAngle: item.startAngle,
53
60
  endAngle: item.endAngle,
54
61
  paddingAngle: item.paddingAngle,
@@ -69,7 +76,24 @@ function PieArcPlot(props) {
69
76
  dataIndex: index
70
77
  }, item);
71
78
  })
72
- }, slotProps?.pieArc), item.dataIndex))
79
+ }, slotProps?.pieArc), item.dataIndex)), focusedItem && /*#__PURE__*/(0, _jsxRuntime.jsx)(Arc, {
80
+ startAngle: focusedItem.startAngle,
81
+ endAngle: focusedItem.endAngle,
82
+ paddingAngle: focusedItem.paddingAngle,
83
+ innerRadius: focusedItem.innerRadius,
84
+ color: focusedItem.color,
85
+ outerRadius: focusedItem.outerRadius,
86
+ cornerRadius: focusedItem.cornerRadius,
87
+ skipAnimation: true,
88
+ stroke: (theme.vars ?? theme).palette.text.primary,
89
+ id: id,
90
+ className: _PieArc.pieArcClasses.focusIndicator,
91
+ dataIndex: focusedIndex,
92
+ isFaded: false,
93
+ isHighlighted: false,
94
+ isFocused: false,
95
+ strokeWidth: 3
96
+ })]
73
97
  }));
74
98
  }
75
99
  process.env.NODE_ENV !== "production" ? PieArcPlot.propTypes = {
@@ -18,7 +18,8 @@ const ChartsSurfaceStyles = styled('svg', {
18
18
  name: 'MuiChartsSurface',
19
19
  slot: 'Root'
20
20
  })(({
21
- ownerState
21
+ ownerState,
22
+ theme
22
23
  }) => ({
23
24
  width: ownerState.width ?? '100%',
24
25
  height: ownerState.height ?? '100%',
@@ -38,14 +39,14 @@ const ChartsSurfaceStyles = styled('svg', {
38
39
  },
39
40
  '&:focus-visible': {
40
41
  // Show focus outline on the SVG container only when using keyboard navigation
41
- outline: 'auto',
42
+ outline: `${(theme.vars ?? theme).palette.text.primary} solid 2px`,
42
43
  '&[data-has-focused-item=true]': {
43
44
  // But not if the chart has a focused children item
44
45
  outline: 'none'
45
46
  }
46
47
  },
47
48
  '& [data-focused=true]': {
48
- outline: 'auto'
49
+ outline: `${(theme.vars ?? theme).palette.text.primary} solid 2px`
49
50
  }
50
51
  }));
51
52
 
@@ -12,6 +12,8 @@ export interface PieArcClasses {
12
12
  * Needs to be suffixed with the series ID: `.${pieArcClasses.series}-${seriesId}`.
13
13
  */
14
14
  series: string;
15
+ /** Styles applied to the focus indicator element. */
16
+ focusIndicator: string;
15
17
  }
16
18
  export type PieArcClassKey = keyof PieArcClasses;
17
19
  interface PieArcOwnerState {
@@ -21,6 +23,7 @@ interface PieArcOwnerState {
21
23
  isFaded: boolean;
22
24
  isHighlighted: boolean;
23
25
  isFocused: boolean;
26
+ stroke?: string;
24
27
  classes?: Partial<PieArcClasses>;
25
28
  }
26
29
  export declare function getPieArcUtilityClass(slot: string): string;
@@ -2,12 +2,13 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
5
- const _excluded = ["classes", "color", "dataIndex", "id", "isFaded", "isHighlighted", "isFocused", "onClick", "cornerRadius", "startAngle", "endAngle", "innerRadius", "outerRadius", "paddingAngle", "skipAnimation"];
5
+ const _excluded = ["className", "classes", "color", "dataIndex", "id", "isFaded", "isHighlighted", "isFocused", "onClick", "cornerRadius", "startAngle", "endAngle", "innerRadius", "outerRadius", "paddingAngle", "skipAnimation", "stroke"];
6
6
  import * as React from 'react';
7
7
  import PropTypes from 'prop-types';
8
+ import clsx from 'clsx';
8
9
  import composeClasses from '@mui/utils/composeClasses';
9
10
  import generateUtilityClass from '@mui/utils/generateUtilityClass';
10
- import { styled } from '@mui/material/styles';
11
+ import { styled, useTheme } from '@mui/material/styles';
11
12
  import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
12
13
  import { useAnimatePieArc } from "../hooks/index.js";
13
14
  import { ANIMATION_DURATION_MS, ANIMATION_TIMING_FUNCTION } from "../internals/animation/animation.js";
@@ -16,7 +17,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
17
  export function getPieArcUtilityClass(slot) {
17
18
  return generateUtilityClass('MuiPieArc', slot);
18
19
  }
19
- export const pieArcClasses = generateUtilityClasses('MuiPieArc', ['root', 'highlighted', 'faded', 'series']);
20
+ export const pieArcClasses = generateUtilityClasses('MuiPieArc', ['root', 'highlighted', 'faded', 'series', 'focusIndicator']);
20
21
  const useUtilityClasses = ownerState => {
21
22
  const {
22
23
  classes,
@@ -34,17 +35,14 @@ const PieArcRoot = styled('path', {
34
35
  name: 'MuiPieArc',
35
36
  slot: 'Root',
36
37
  overridesResolver: (_, styles) => styles.arc // FIXME: Inconsistent naming with slot
37
- })(({
38
- theme
39
- }) => ({
40
- // Got to move stroke to an element prop instead of style.
41
- stroke: (theme.vars || theme).palette.background.paper,
38
+ })({
42
39
  transitionProperty: 'opacity, fill, filter',
43
40
  transitionDuration: `${ANIMATION_DURATION_MS}ms`,
44
41
  transitionTimingFunction: ANIMATION_TIMING_FUNCTION
45
- }));
42
+ });
46
43
  const PieArc = /*#__PURE__*/React.forwardRef(function PieArc(props, ref) {
47
44
  const {
45
+ className,
48
46
  classes: innerClasses,
49
47
  color,
50
48
  dataIndex,
@@ -59,9 +57,12 @@ const PieArc = /*#__PURE__*/React.forwardRef(function PieArc(props, ref) {
59
57
  innerRadius,
60
58
  outerRadius,
61
59
  paddingAngle,
62
- skipAnimation
60
+ skipAnimation,
61
+ stroke: strokeProp
63
62
  } = props,
64
63
  other = _objectWithoutPropertiesLoose(props, _excluded);
64
+ const theme = useTheme();
65
+ const stroke = strokeProp ?? (theme.vars || theme).palette.background.paper;
65
66
  const ownerState = {
66
67
  id,
67
68
  dataIndex,
@@ -91,15 +92,15 @@ const PieArc = /*#__PURE__*/React.forwardRef(function PieArc(props, ref) {
91
92
  onClick: onClick,
92
93
  cursor: onClick ? 'pointer' : 'unset',
93
94
  ownerState: ownerState,
94
- className: classes.root,
95
+ className: clsx(classes.root, className),
95
96
  fill: ownerState.color,
96
97
  opacity: ownerState.isFaded ? 0.3 : 1,
97
98
  filter: ownerState.isHighlighted ? 'brightness(120%)' : 'none',
99
+ stroke: stroke,
98
100
  strokeWidth: 1,
99
101
  strokeLinejoin: "round",
100
102
  "data-highlighted": ownerState.isHighlighted || undefined,
101
- "data-faded": ownerState.isFaded || undefined,
102
- "data-focused": isFocused || undefined
103
+ "data-faded": ownerState.isFaded || undefined
103
104
  }, other, interactionProps, animatedProps));
104
105
  });
105
106
  if (process.env.NODE_ENV !== "production") PieArc.displayName = "PieArc";
@@ -5,9 +5,11 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
5
5
  const _excluded = ["slots", "slotProps", "innerRadius", "outerRadius", "cornerRadius", "paddingAngle", "id", "highlighted", "faded", "data", "onItemClick", "skipAnimation"];
6
6
  import * as React from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { PieArc } from "./PieArc.js";
8
+ import { useTheme } from '@mui/material/styles';
9
+ import { useFocusedItem } from "../hooks/useFocusedItem.js";
10
+ import { PieArc, pieArcClasses } from "./PieArc.js";
9
11
  import { useTransformData } from "./dataTransform/useTransformData.js";
10
- import { jsx as _jsx } from "react/jsx-runtime";
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
13
  function PieArcPlot(props) {
12
14
  const {
13
15
  slots,
@@ -26,6 +28,7 @@ function PieArcPlot(props) {
26
28
  skipAnimation
27
29
  } = props,
28
30
  other = _objectWithoutPropertiesLoose(props, _excluded);
31
+ const theme = useTheme();
29
32
  const transformedData = useTransformData({
30
33
  innerRadius,
31
34
  outerRadius,
@@ -36,12 +39,16 @@ function PieArcPlot(props) {
36
39
  faded,
37
40
  data
38
41
  });
42
+ const {
43
+ dataIndex: focusedIndex = -1
44
+ } = useFocusedItem() ?? {};
45
+ const focusedItem = focusedIndex !== -1 ? transformedData[focusedIndex] : null;
39
46
  if (data.length === 0) {
40
47
  return null;
41
48
  }
42
49
  const Arc = slots?.pieArc ?? PieArc;
43
- return /*#__PURE__*/_jsx("g", _extends({}, other, {
44
- children: transformedData.map((item, index) => /*#__PURE__*/_jsx(Arc, _extends({
50
+ return /*#__PURE__*/_jsxs("g", _extends({}, other, {
51
+ children: [transformedData.map((item, index) => /*#__PURE__*/_jsx(Arc, _extends({
45
52
  startAngle: item.startAngle,
46
53
  endAngle: item.endAngle,
47
54
  paddingAngle: item.paddingAngle,
@@ -62,7 +69,24 @@ function PieArcPlot(props) {
62
69
  dataIndex: index
63
70
  }, item);
64
71
  })
65
- }, slotProps?.pieArc), item.dataIndex))
72
+ }, slotProps?.pieArc), item.dataIndex)), focusedItem && /*#__PURE__*/_jsx(Arc, {
73
+ startAngle: focusedItem.startAngle,
74
+ endAngle: focusedItem.endAngle,
75
+ paddingAngle: focusedItem.paddingAngle,
76
+ innerRadius: focusedItem.innerRadius,
77
+ color: focusedItem.color,
78
+ outerRadius: focusedItem.outerRadius,
79
+ cornerRadius: focusedItem.cornerRadius,
80
+ skipAnimation: true,
81
+ stroke: (theme.vars ?? theme).palette.text.primary,
82
+ id: id,
83
+ className: pieArcClasses.focusIndicator,
84
+ dataIndex: focusedIndex,
85
+ isFaded: false,
86
+ isHighlighted: false,
87
+ isFocused: false,
88
+ strokeWidth: 3
89
+ })]
66
90
  }));
67
91
  }
68
92
  process.env.NODE_ENV !== "production" ? PieArcPlot.propTypes = {
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-charts v8.12.0
2
+ * @mui/x-charts v8.13.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,48 +1,67 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import { GestureManager, MoveGesture, PanGesture, PinchGesture, PressGesture, TapGesture, TurnWheelGesture } from '@mui/x-internal-gestures/core';
4
+ import { GestureManager, MoveGesture, PanGesture, PinchGesture, PressGesture, TapAndDragGesture, TapGesture, TurnWheelGesture } from '@mui/x-internal-gestures/core';
5
5
  const preventDefault = event => event.preventDefault();
6
6
  export const useChartInteractionListener = ({
7
7
  svgRef
8
8
  }) => {
9
+ const gestureManagerRef = React.useRef(null);
9
10
  React.useEffect(() => {
10
11
  const svg = svgRef.current;
11
- if (!svg) {
12
+ if (!gestureManagerRef.current) {
13
+ gestureManagerRef.current = new GestureManager({
14
+ gestures: [
15
+ // We separate the zoom gestures from the gestures that are not zoom related
16
+ // This allows us to configure the zoom gestures based on the zoom configuration.
17
+ new PanGesture({
18
+ name: 'pan',
19
+ threshold: 0,
20
+ maxPointers: 1
21
+ }), new PanGesture({
22
+ name: 'zoomPan',
23
+ threshold: 0,
24
+ maxPointers: 1,
25
+ preventIf: ['zoomTapAndDrag']
26
+ }), new MoveGesture({
27
+ name: 'move',
28
+ preventIf: ['pan', 'zoomPinch', 'zoomPan'] // Prevent move gesture when pan is active
29
+ }), new PinchGesture({
30
+ name: 'zoomPinch',
31
+ threshold: 5,
32
+ preventIf: ['pan', 'zoomPan']
33
+ }), new TurnWheelGesture({
34
+ name: 'zoomTurnWheel',
35
+ sensitivity: 0.01,
36
+ initialDelta: 1
37
+ }), new TapGesture({
38
+ name: 'tap',
39
+ maxDistance: 10,
40
+ preventIf: ['pan', 'zoomPan', 'zoomPinch']
41
+ }), new PressGesture({
42
+ name: 'quickPress',
43
+ duration: 50,
44
+ maxDistance: 10
45
+ }), new TapAndDragGesture({
46
+ name: 'zoomTapAndDrag',
47
+ tapMaxDistance: 10,
48
+ dragThreshold: 10,
49
+ dragTimeout: 1000
50
+ })]
51
+ });
52
+ }
53
+
54
+ // Assign gesture manager after initialization
55
+ const gestureManager = gestureManagerRef.current;
56
+ if (!svg || !gestureManager) {
12
57
  return undefined;
13
58
  }
14
- const gestureManager = new GestureManager({
15
- gestures: [new PanGesture({
16
- name: 'pan',
17
- threshold: 0,
18
- maxPointers: 1
19
- }), new MoveGesture({
20
- name: 'move',
21
- preventIf: ['pan', 'pinch'] // Prevent move gesture when pan is active
22
- }), new PinchGesture({
23
- name: 'pinch',
24
- threshold: 5,
25
- preventIf: ['pan']
26
- }), new TurnWheelGesture({
27
- name: 'turnWheel',
28
- sensitivity: 0.01,
29
- initialDelta: 1
30
- }), new TapGesture({
31
- name: 'tap',
32
- maxDistance: 10,
33
- preventIf: ['pan', 'pinch']
34
- }), new PressGesture({
35
- name: 'quickPress',
36
- duration: 50,
37
- maxDistance: 10
38
- })]
39
- });
40
- gestureManager.registerElement(['pan', 'move', 'pinch', 'turnWheel', 'tap', 'quickPress'], svg);
59
+ gestureManager.registerElement(['pan', 'move', 'zoomPinch', 'zoomPan', 'zoomTurnWheel', 'tap', 'quickPress', 'zoomTapAndDrag'], svg);
41
60
  return () => {
42
61
  // Cleanup gesture manager
43
- gestureManager.destroy();
62
+ gestureManager.unregisterAllGestures(svg);
44
63
  };
45
- }, [svgRef]);
64
+ }, [svgRef, gestureManagerRef]);
46
65
  const addInteractionListener = React.useCallback((interaction, callback, options) => {
47
66
  // Forcefully cast the svgRef to any, it is annoying to fix the types.
48
67
  const svg = svgRef.current;
@@ -51,6 +70,14 @@ export const useChartInteractionListener = ({
51
70
  cleanup: () => svg?.removeEventListener(interaction, callback)
52
71
  };
53
72
  }, [svgRef]);
73
+ const updateZoomInteractionListeners = React.useCallback((interaction, options) => {
74
+ const svg = svgRef.current;
75
+ const gestureManager = gestureManagerRef.current;
76
+ if (!gestureManager || !svg) {
77
+ return;
78
+ }
79
+ gestureManager.setGestureOptions(interaction, svg, options ?? {});
80
+ }, [svgRef, gestureManagerRef]);
54
81
  React.useEffect(() => {
55
82
  const svg = svgRef.current;
56
83
 
@@ -67,7 +94,8 @@ export const useChartInteractionListener = ({
67
94
  }, [svgRef]);
68
95
  return {
69
96
  instance: {
70
- addInteractionListener
97
+ addInteractionListener,
98
+ updateZoomInteractionListeners
71
99
  }
72
100
  };
73
101
  };