@mui/x-charts-pro 8.5.2 → 8.5.3

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 (58) hide show
  1. package/CHANGELOG.md +96 -11
  2. package/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  3. package/ChartZoomSlider/internals/ChartAxisZoomSlider.js +1 -1
  4. package/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.js +20 -31
  5. package/ChartZoomSlider/internals/ChartAxisZoomSliderTrack.js +1 -8
  6. package/ChartZoomSlider/internals/zoom-utils.d.ts +3 -1
  7. package/ChartZoomSlider/internals/zoom-utils.js +19 -8
  8. package/FunnelChart/FunnelPlot.js +56 -40
  9. package/FunnelChart/FunnelSection.js +2 -0
  10. package/FunnelChart/curves/bump.d.ts +3 -3
  11. package/FunnelChart/curves/bump.js +3 -0
  12. package/FunnelChart/curves/curve.types.d.ts +14 -1
  13. package/FunnelChart/curves/getFunnelCurve.d.ts +7 -2
  14. package/FunnelChart/curves/linear.d.ts +3 -3
  15. package/FunnelChart/curves/linear.js +23 -18
  16. package/FunnelChart/curves/pyramid.d.ts +3 -3
  17. package/FunnelChart/curves/pyramid.js +17 -12
  18. package/FunnelChart/curves/step-pyramid.d.ts +5 -5
  19. package/FunnelChart/curves/step-pyramid.js +20 -18
  20. package/FunnelChart/curves/step.d.ts +3 -3
  21. package/FunnelChart/curves/step.js +14 -12
  22. package/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.d.ts +18 -1444
  23. package/FunnelChart/labelUtils.d.ts +4 -12
  24. package/FunnelChart/labelUtils.js +43 -44
  25. package/esm/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  26. package/esm/ChartZoomSlider/internals/ChartAxisZoomSlider.js +1 -1
  27. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderActiveTrack.js +21 -32
  28. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderTrack.js +1 -8
  29. package/esm/ChartZoomSlider/internals/zoom-utils.d.ts +3 -1
  30. package/esm/ChartZoomSlider/internals/zoom-utils.js +19 -9
  31. package/esm/FunnelChart/FunnelPlot.js +56 -40
  32. package/esm/FunnelChart/FunnelSection.js +2 -0
  33. package/esm/FunnelChart/curves/bump.d.ts +3 -3
  34. package/esm/FunnelChart/curves/bump.js +3 -0
  35. package/esm/FunnelChart/curves/curve.types.d.ts +14 -1
  36. package/esm/FunnelChart/curves/getFunnelCurve.d.ts +7 -2
  37. package/esm/FunnelChart/curves/linear.d.ts +3 -3
  38. package/esm/FunnelChart/curves/linear.js +23 -18
  39. package/esm/FunnelChart/curves/pyramid.d.ts +3 -3
  40. package/esm/FunnelChart/curves/pyramid.js +17 -12
  41. package/esm/FunnelChart/curves/step-pyramid.d.ts +5 -5
  42. package/esm/FunnelChart/curves/step-pyramid.js +20 -18
  43. package/esm/FunnelChart/curves/step.d.ts +3 -3
  44. package/esm/FunnelChart/curves/step.js +14 -12
  45. package/esm/FunnelChart/funnelAxisPlugin/useChartFunnelAxisRendering.selectors.d.ts +18 -1444
  46. package/esm/FunnelChart/labelUtils.d.ts +4 -12
  47. package/esm/FunnelChart/labelUtils.js +43 -44
  48. package/esm/index.js +1 -1
  49. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +16 -595
  50. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +2 -2
  51. package/index.js +1 -1
  52. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +16 -595
  53. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +2 -2
  54. package/package.json +5 -5
  55. package/FunnelChart/positionGetter.d.ts +0 -1
  56. package/FunnelChart/positionGetter.js +0 -5
  57. package/esm/FunnelChart/positionGetter.d.ts +0 -1
  58. package/esm/FunnelChart/positionGetter.js +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,101 @@
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.5.3
9
+
10
+ _Jun 19, 2025_
11
+
12
+ We'd like to extend a big thank you to the 10 contributors who made this release possible. Here are some highlights ✨:
13
+
14
+ - 📚 Documentation improvements
15
+ - 🐞 Bugfixes
16
+
17
+ Special thanks go out to the community members for their valuable contributions:
18
+ @alisasanib, @arminmeh, @sai6855
19
+
20
+ The following are all team members who have contributed to this release:
21
+ @alexfauquette, @bernardobelchior, @flaviendelangle, @JCQuintas, @LukasTy, @MBilalShafi, @oliviertassinari
22
+
23
+ ### Data Grid
24
+
25
+ #### `@mui/x-data-grid@8.5.3`
26
+
27
+ - [DataGrid] Fix export menu button tooltip being interactive when menu is open (#18327) @bernardobelchior
28
+ - [DataGrid] Fix column menu scroll close (#18065) @alisasanib
29
+ - [DataGrid] Fix page size issue with data source (#18419) @MBilalShafi
30
+
31
+ #### `@mui/x-data-grid-pro@8.5.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
32
+
33
+ Same changes as in `@mui/x-data-grid@8.5.3`, plus:
34
+
35
+ - [DataGridPro] Ignore missing `rowCount` response when new children are fetched with the data source (#17711) @arminmeh
36
+
37
+ #### `@mui/x-data-grid-premium@8.5.3` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
38
+
39
+ Same changes as in `@mui/x-data-grid-pro@8.5.3`.
40
+
41
+ ### Date and Time Pickers
42
+
43
+ #### `@mui/x-date-pickers@8.5.3`
44
+
45
+ - [pickers] Add `inputSizeSmall` to classes interface (#18242) @sai6855
46
+
47
+ #### `@mui/x-date-pickers-pro@8.5.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
48
+
49
+ Same changes as in `@mui/x-date-pickers@8.5.3`.
50
+
51
+ ### Charts
52
+
53
+ #### `@mui/x-charts@8.5.3`
54
+
55
+ - [charts] Add item class to list item around each series in legend (#18411) @bernardobelchior
56
+ - [charts] Allow `tabIndex` in surface and legend (#18344) @JCQuintas
57
+ - [charts] Explore selector typing (#18362) @alexfauquette
58
+ - [charts] Fix highlight with number ids (#18423) @alexfauquette
59
+ - [charts] Make scatter chart use data attributes (#18048) @alexfauquette
60
+
61
+ #### `@mui/x-charts-pro@8.5.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
62
+
63
+ Same changes as in `@mui/x-charts@8.5.3`, plus:
64
+
65
+ - [charts-pro] Add data-series to elements of funnel chart (#18067) @JCQuintas
66
+ - [charts-pro] Hide values outside minStart and maxEnd in zoom slider (#18336) @bernardobelchior
67
+ - [charts-pro] Fix `FunnelChart` label positioning with different curves (#18354) @JCQuintas
68
+
69
+ ### Tree View
70
+
71
+ #### `@mui/x-tree-view@8.5.3`
72
+
73
+ Internal changes.
74
+
75
+ #### `@mui/x-tree-view-pro@8.5.3` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
76
+
77
+ Same changes as in `@mui/x-tree-view@8.5.3`.
78
+
79
+ ### Codemod
80
+
81
+ #### `@mui/x-codemod@8.5.3`
82
+
83
+ Internal changes.
84
+
85
+ ### Docs
86
+
87
+ - [docs] Fix 404 in charts docs (#18440) @alexfauquette
88
+ - [docs][pickers] Fix adapter version resolving when opening demo to edit (#18363) @LukasTy
89
+
90
+ ### Core
91
+
92
+ - [core] Fix pnpm valelint error (#18420) @oliviertassinari
93
+
94
+ ### Miscellaneous
95
+
96
+ - [code-infra] Add back a `Playwright` renovate group (#18397) @LukasTy
97
+ - [code-infra] Setup `CODEOWNERS` for charts repositories (#18418) @JCQuintas
98
+ - [code-infra] Strengthen `URL` usage for test config (#18444) @LukasTy
99
+ - [code-infra] Use `vitest` bundled types (#17758) @JCQuintas
100
+ - [infra] Stabilise tests by removing babel and plugins from vitest (#18341) @JCQuintas
101
+ - [infra] Add automated release PR creation script (#18345) @michelengelen
102
+
8
103
  ## 8.5.2
9
104
 
10
105
  _Jun 12, 2025_
@@ -94,7 +189,7 @@ Same changes as in `@mui/x-tree-view@8.5.2`.
94
189
  - [code-infra] Revert `React` to `19.0.0` (#18265) @LukasTy
95
190
  - [code-infra] Use `catalog` for reused dependencies (#18302) @LukasTy
96
191
  - [infra] Remove unused karma/mocha deps and files (#18340) @JCQuintas
97
- - [infra] Update github label references to use 'scope' instead of 'component' (#18260) @michelengelen
192
+ - [infra] Update GitHub label references to use 'scope' instead of 'component' (#18260) @michelengelen
98
193
  - [infra] Use a single browser server in CI (#18230) @JCQuintas
99
194
 
100
195
  ## 8.5.1
@@ -189,15 +284,6 @@ Same changes as in `@mui/x-tree-view@8.5.1`.
189
284
 
190
285
  ### Core
191
286
 
192
- - chore(deps): bump @next/eslint-plugin-next to 15.3.3 (#18155) @renovate[bot]
193
- - chore(deps): bump @types/lodash to ^4.17.17 (#17990) @renovate[bot]
194
- - chore(deps): bump babel (#18157) @renovate[bot]
195
- - chore(deps): bump eslint to ^9.28.0 (#17352) @renovate[bot]
196
- - chore(deps): bump material ui (#17802) @renovate[bot]
197
- - chore(deps): bump next to ^15.3.3 (#18159) @renovate[bot]
198
- - chore(deps): bump ossf/scorecard-action action to v2.4.2 (#18160) @renovate[bot]
199
- - chore(deps): bump react-router to ^7.6.1 (#18162) @renovate[bot]
200
- - chore(deps): bump yargs to ^18.0.0 (#18169) @renovate[bot]
201
287
  - [code-infra] Different approach to console testing for `processRowUpdate` (#18213) @JCQuintas
202
288
  - [code-infra] Fix act warnings in DataGrid/toolbar (#18207) @JCQuintas
203
289
  - [code-infra] Remove `istanbul` references (#18194) @JCQuintas
@@ -4641,7 +4727,6 @@ No changes since `@mui/x-charts@7.22.2`.
4641
4727
  - [docs] Add `next` version links (#15423) @LukasTy
4642
4728
  - [docs] Use the `loading` state in the demos (#15538) @cherniavskii
4643
4729
  - [docs] Add data caching to lazy loaded detail panel demo (#15506) @cherniavskii
4644
-
4645
4730
  - [code-infra] Tentative fix for Argos flaky screenshot tests (#15399) @JCQuintas
4646
4731
  - [docs-infra] Transpile `.ts` demo files (#15421) @KenanYusuf
4647
4732
  - [core] Clarify release version bump strategy (#15536) @cherniavskii
@@ -18,7 +18,7 @@ var _material = require("../internals/material");
18
18
  var _allPlugins = require("../internals/plugins/allPlugins");
19
19
  var _useChartDataProviderProProps = require("./useChartDataProviderProProps");
20
20
  var _jsxRuntime = require("react/jsx-runtime");
21
- const releaseInfo = "MTc0OTY3OTIwMDAwMA==";
21
+ const releaseInfo = "MTc1MDI4NDAwMDAwMA==";
22
22
  const packageIdentifier = 'x-charts-pro';
23
23
  /**
24
24
  * Orchestrates the data providers for the chart components and hooks.
@@ -24,7 +24,7 @@ function ChartAxisZoomSlider({
24
24
  }) {
25
25
  const store = (0, _internals.useStore)();
26
26
  const drawingArea = (0, _internals.useDrawingArea)();
27
- const zoomData = (0, _internals.useSelector)(store, _useChartProZoom.selectorChartAxisZoomData, axisId);
27
+ const zoomData = (0, _internals.useSelector)(store, _useChartProZoom.selectorChartAxisZoomData, [axisId]);
28
28
  const [showTooltip, setShowTooltip] = React.useState(false);
29
29
  const {
30
30
  xAxis
@@ -40,7 +40,7 @@ function ChartAxisZoomSliderActiveTrack({
40
40
  svgRef
41
41
  } = (0, _internals.useChartContext)();
42
42
  const store = (0, _internals.useStore)();
43
- const axis = (0, _internals.useSelector)(store, _internals.selectorChartAxis, axisId);
43
+ const axis = (0, _internals.useSelector)(store, _internals.selectorChartAxis, [axisId]);
44
44
  const drawingArea = (0, _internals.useDrawingArea)();
45
45
  const activePreviewRectRef = React.useRef(null);
46
46
  const [startThumbEl, setStartThumbEl] = React.useState(null);
@@ -56,10 +56,6 @@ function ChartAxisZoomSliderActiveTrack({
56
56
  if (!activePreviewRect) {
57
57
  return;
58
58
  }
59
-
60
- /* min and max values of zoom to ensure the pointer anchor in the slider is maintained */
61
- let pointerZoomMin;
62
- let pointerZoomMax;
63
59
  let prevPointerZoom = 0;
64
60
  const onPointerMove = (0, _rafThrottle.rafThrottle)(event => {
65
61
  const element = svgRef.current;
@@ -67,11 +63,10 @@ function ChartAxisZoomSliderActiveTrack({
67
63
  return;
68
64
  }
69
65
  const point = (0, _internals.getSVGPoint)(element, event);
70
- let pointerZoom = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, point);
66
+ const pointerZoom = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, point);
71
67
  if (pointerZoom === null) {
72
68
  return;
73
69
  }
74
- pointerZoom = Math.max(pointerZoomMin, Math.min(pointerZoomMax, pointerZoom));
75
70
  const deltaZoom = pointerZoom - prevPointerZoom;
76
71
  prevPointerZoom = pointerZoom;
77
72
  instance.moveZoomRange(axisId, deltaZoom);
@@ -95,8 +90,6 @@ function ChartAxisZoomSliderActiveTrack({
95
90
  return;
96
91
  }
97
92
  prevPointerZoom = pointerDownZoom;
98
- pointerZoomMin = pointerDownZoom - axisZoomData.start;
99
- pointerZoomMax = 100 - (axisZoomData.end - pointerDownZoom);
100
93
  document.addEventListener('pointerup', onPointerUp);
101
94
  activePreviewRect.addEventListener('pointermove', onPointerMove);
102
95
  };
@@ -137,23 +130,12 @@ function ChartAxisZoomSliderActiveTrack({
137
130
  }
138
131
  const point = (0, _internals.getSVGPoint)(element, event);
139
132
  instance.setZoomData(prevZoomData => {
140
- const {
141
- left,
142
- top,
143
- width,
144
- height
145
- } = (0, _internals.selectorChartDrawingArea)(store.getSnapshot());
146
133
  const zoomOptions = (0, _internals.selectorChartAxisZoomOptionsLookup)(store.getSnapshot(), axisId);
147
134
  return prevZoomData.map(zoom => {
148
135
  if (zoom.axisId === axisId) {
149
- let newEnd;
150
- if (axisDirection === 'x') {
151
- newEnd = (point.x - left) / width * 100;
152
- } else {
153
- newEnd = (top + height - point.y) / height * 100;
154
- }
155
- if (reverse) {
156
- newEnd = 100 - newEnd;
136
+ const newEnd = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, point);
137
+ if (newEnd === null) {
138
+ return zoom;
157
139
  }
158
140
  return (0, _extends2.default)({}, zoom, {
159
141
  end: (0, _zoomUtils.calculateZoomEnd)(newEnd, zoom, zoomOptions)
@@ -171,14 +153,21 @@ function ChartAxisZoomSliderActiveTrack({
171
153
  let startThumbY;
172
154
  let endThumbX;
173
155
  let endThumbY;
156
+ const {
157
+ minStart,
158
+ maxEnd
159
+ } = (0, _internals.selectorChartAxisZoomOptionsLookup)(store.getSnapshot(), axisId);
160
+ const range = maxEnd - minStart;
161
+ const zoomStart = Math.max(minStart, zoomData.start);
162
+ const zoomEnd = Math.min(zoomData.end, maxEnd);
174
163
  if (axisDirection === 'x') {
175
- previewX = zoomData.start / 100 * drawingArea.width;
164
+ previewX = (zoomStart - minStart) / range * drawingArea.width;
176
165
  previewY = 0;
177
- previewWidth = drawingArea.width * (zoomData.end - zoomData.start) / 100;
166
+ previewWidth = drawingArea.width * (zoomEnd - zoomStart) / range;
178
167
  previewHeight = _constants.ZOOM_SLIDER_ACTIVE_TRACK_SIZE;
179
- startThumbX = zoomData.start / 100 * drawingArea.width;
168
+ startThumbX = (zoomStart - minStart) / range * drawingArea.width;
180
169
  startThumbY = 0;
181
- endThumbX = zoomData.end / 100 * drawingArea.width;
170
+ endThumbX = (zoomEnd - minStart) / range * drawingArea.width;
182
171
  endThumbY = 0;
183
172
  if (reverse) {
184
173
  previewX = drawingArea.width - previewX - previewWidth;
@@ -189,13 +178,13 @@ function ChartAxisZoomSliderActiveTrack({
189
178
  endThumbX -= previewThumbWidth / 2;
190
179
  } else {
191
180
  previewX = 0;
192
- previewY = drawingArea.height - zoomData.end / 100 * drawingArea.height;
181
+ previewY = drawingArea.height - (zoomEnd - minStart) / range * drawingArea.height;
193
182
  previewWidth = _constants.ZOOM_SLIDER_ACTIVE_TRACK_SIZE;
194
- previewHeight = drawingArea.height * (zoomData.end - zoomData.start) / 100;
183
+ previewHeight = drawingArea.height * (zoomEnd - zoomStart) / range;
195
184
  startThumbX = 0;
196
- startThumbY = drawingArea.height - zoomData.start / 100 * drawingArea.height;
185
+ startThumbY = drawingArea.height - (zoomStart - minStart) / range * drawingArea.height;
197
186
  endThumbX = 0;
198
- endThumbY = drawingArea.height - zoomData.end / 100 * drawingArea.height;
187
+ endThumbY = drawingArea.height - (zoomEnd - minStart) / range * drawingArea.height;
199
188
  if (reverse) {
200
189
  previewY = drawingArea.height - previewY - previewHeight;
201
190
  startThumbY = drawingArea.height - startThumbY;
@@ -63,17 +63,10 @@ function ChartAxisZoomSliderTrack(_ref) {
63
63
  return;
64
64
  }
65
65
  const pointerDownPoint = (0, _internals.getSVGPoint)(element, event);
66
- let zoomFromPointerDown = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, pointerDownPoint);
66
+ const zoomFromPointerDown = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, pointerDownPoint);
67
67
  if (zoomFromPointerDown === null) {
68
68
  return;
69
69
  }
70
- const {
71
- minStart,
72
- maxEnd
73
- } = (0, _internals.selectorChartAxisZoomOptionsLookup)(store.getSnapshot(), axisId);
74
-
75
- // Ensure the zoomFromPointerDown is within the min and max range
76
- zoomFromPointerDown = Math.max(Math.min(zoomFromPointerDown, maxEnd), minStart);
77
70
  const onPointerMove = (0, _rafThrottle.rafThrottle)(function onPointerMove(pointerMoveEvent) {
78
71
  const pointerMovePoint = (0, _internals.getSVGPoint)(element, pointerMoveEvent);
79
72
  const zoomFromPointerMove = (0, _zoomUtils.calculateZoomFromPoint)(store.getSnapshot(), axisId, pointerMovePoint);
@@ -1,4 +1,6 @@
1
- import { AxisId, ChartState, DefaultizedZoomOptions, ZoomData } from '@mui/x-charts/internals';
1
+ import { AxisId, ChartState, DefaultedXAxis, DefaultedYAxis, DefaultizedZoomOptions, ZoomData } from '@mui/x-charts/internals';
2
+ import { ChartDrawingArea } from '@mui/x-charts/hooks';
2
3
  export declare function calculateZoomFromPoint(state: ChartState<any>, axisId: AxisId, point: DOMPoint): number | null;
4
+ export declare function calculateZoomFromPointImpl(drawingArea: ChartDrawingArea, axis: Pick<DefaultedXAxis | DefaultedYAxis, 'position' | 'reverse'>, zoomOptions: Pick<DefaultizedZoomOptions, 'minStart' | 'maxEnd'>, point: Pick<DOMPoint, 'x' | 'y'>): number;
3
5
  export declare function calculateZoomStart(newStart: number, currentZoom: ZoomData, options: Pick<DefaultizedZoomOptions, 'minStart' | 'minSpan' | 'maxSpan'>): number;
4
6
  export declare function calculateZoomEnd(newEnd: number, currentZoom: ZoomData, options: Pick<DefaultizedZoomOptions, 'maxEnd' | 'minSpan' | 'maxSpan'>): number;
@@ -5,28 +5,39 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.calculateZoomEnd = calculateZoomEnd;
7
7
  exports.calculateZoomFromPoint = calculateZoomFromPoint;
8
+ exports.calculateZoomFromPointImpl = calculateZoomFromPointImpl;
8
9
  exports.calculateZoomStart = calculateZoomStart;
9
10
  var _internals = require("@mui/x-charts/internals");
10
11
  function calculateZoomFromPoint(state, axisId, point) {
12
+ const axis = (0, _internals.selectorChartRawAxis)(state, axisId);
13
+ if (!axis) {
14
+ return null;
15
+ }
16
+ return calculateZoomFromPointImpl((0, _internals.selectorChartDrawingArea)(state), axis, (0, _internals.selectorChartAxisZoomOptionsLookup)(state, axisId), point);
17
+ }
18
+ function calculateZoomFromPointImpl(drawingArea, axis, zoomOptions, point) {
11
19
  const {
12
20
  left,
13
21
  top,
14
22
  height,
15
23
  width
16
- } = (0, _internals.selectorChartDrawingArea)(state);
17
- const axis = (0, _internals.selectorChartRawAxis)(state, axisId);
18
- if (!axis) {
19
- return null;
20
- }
24
+ } = drawingArea;
25
+ const {
26
+ minStart,
27
+ maxEnd
28
+ } = zoomOptions;
21
29
  const axisDirection = axis.position === 'right' || axis.position === 'left' ? 'y' : 'x';
30
+ const range = maxEnd - minStart;
22
31
  let pointerZoom;
23
32
  if (axisDirection === 'x') {
24
- pointerZoom = (point.x - left) / width * 100;
33
+ pointerZoom = (point.x - left) / width * range;
25
34
  } else {
26
- pointerZoom = (top + height - point.y) / height * 100;
35
+ pointerZoom = (top + height - point.y) / height * range;
27
36
  }
28
37
  if (axis.reverse) {
29
- pointerZoom = 100 - pointerZoom;
38
+ pointerZoom = maxEnd - pointerZoom;
39
+ } else {
40
+ pointerZoom += minStart;
30
41
  }
31
42
  return pointerZoom;
32
43
  }
@@ -105,21 +105,21 @@ const useAggregatedData = () => {
105
105
  min: minPoint,
106
106
  max: maxPoint
107
107
  });
108
- const line = (0, _d3Shape.line)().x(d => xPosition(d.x, dataIndex, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).y(d => yPosition(d.y, dataIndex, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).curve(curve);
108
+ const bandPoints = curve({}).processPoints(values.map(v => ({
109
+ x: xPosition(v.x, dataIndex, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth),
110
+ y: yPosition(v.y, dataIndex, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)
111
+ })));
112
+ const line = (0, _d3Shape.line)().x(v => v.x).y(v => v.y).curve(curve);
109
113
  return {
110
- d: line(values),
114
+ d: line(bandPoints),
111
115
  color,
112
116
  id,
113
117
  seriesId,
114
118
  dataIndex,
115
119
  variant: currentSeries.variant,
116
120
  label: sectionLabel !== false && (0, _extends2.default)({}, (0, _labelUtils.positionLabel)((0, _extends2.default)({}, sectionLabel, {
117
- xPosition,
118
- yPosition,
119
121
  isHorizontal,
120
- values,
121
- dataIndex,
122
- baseScaleData: baseScaleConfig.data ?? []
122
+ values: bandPoints
123
123
  })), (0, _labelUtils.alignLabel)(sectionLabel ?? {}), {
124
124
  value: valueFormatter ? valueFormatter(currentSeries.data[dataIndex], {
125
125
  dataIndex
@@ -128,7 +128,7 @@ const useAggregatedData = () => {
128
128
  };
129
129
  });
130
130
  });
131
- return result.flat();
131
+ return result;
132
132
  }, [seriesData, xAxis, xAxisIds, yAxis, yAxisIds, gap]);
133
133
  return allData;
134
134
  };
@@ -139,41 +139,57 @@ function FunnelPlot(props) {
139
139
  other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
140
140
  const data = useAggregatedData();
141
141
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(React.Fragment, {
142
- children: [data.map(({
143
- d,
144
- color,
145
- id,
146
- seriesId,
147
- dataIndex,
148
- variant
149
- }) => /*#__PURE__*/(0, _react.createElement)(_FunnelSection.FunnelSection, (0, _extends2.default)({}, other, {
150
- d: d,
151
- color: color,
152
- key: id,
153
- dataIndex: dataIndex,
154
- seriesId: seriesId,
155
- variant: variant,
156
- onClick: onItemClick && (event => {
157
- onItemClick(event, {
158
- type: 'funnel',
142
+ children: [data.map(series => {
143
+ if (series.length === 0) {
144
+ return null;
145
+ }
146
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("g", {
147
+ "data-series": series[0].seriesId,
148
+ children: series.map(({
149
+ d,
150
+ color,
151
+ id,
159
152
  seriesId,
160
- dataIndex
161
- });
162
- })
163
- }))), data.map(({
164
- id,
165
- label,
166
- seriesId,
167
- dataIndex
168
- }) => {
169
- if (!label || !label.value) {
153
+ dataIndex,
154
+ variant
155
+ }) => /*#__PURE__*/(0, _react.createElement)(_FunnelSection.FunnelSection, (0, _extends2.default)({}, other, {
156
+ d: d,
157
+ color: color,
158
+ key: id,
159
+ dataIndex: dataIndex,
160
+ seriesId: seriesId,
161
+ variant: variant,
162
+ onClick: onItemClick && (event => {
163
+ onItemClick(event, {
164
+ type: 'funnel',
165
+ seriesId,
166
+ dataIndex
167
+ });
168
+ })
169
+ })))
170
+ }, series[0].seriesId);
171
+ }), data.map(series => {
172
+ if (series.length === 0) {
170
173
  return null;
171
174
  }
172
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_FunnelSectionLabel.FunnelSectionLabel, (0, _extends2.default)({
173
- label: label,
174
- dataIndex: dataIndex,
175
- seriesId: seriesId
176
- }, other), id);
175
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("g", {
176
+ "data-series": series[0].seriesId,
177
+ children: series.map(({
178
+ id,
179
+ label,
180
+ seriesId,
181
+ dataIndex
182
+ }) => {
183
+ if (!label || !label.value) {
184
+ return null;
185
+ }
186
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_FunnelSectionLabel.FunnelSectionLabel, (0, _extends2.default)({
187
+ label: label,
188
+ dataIndex: dataIndex,
189
+ seriesId: seriesId
190
+ }, other), id);
191
+ })
192
+ }, series[0].seriesId);
177
193
  })]
178
194
  });
179
195
  }
@@ -60,6 +60,8 @@ const FunnelSection = exports.FunnelSection = (0, _internals.consumeSlots)('MuiF
60
60
  strokeWidth: isOutlined ? 1.5 : 0,
61
61
  cursor: onClick ? 'pointer' : 'unset',
62
62
  onClick: onClick,
63
+ "data-highlighted": isHighlighted || undefined,
64
+ "data-faded": isFaded || undefined,
63
65
  className: (0, _clsx.default)(classes?.root, className, isOutlined ? classes?.outlined : classes?.filled, isHighlighted && classes?.highlighted, isFaded && classes?.faded)
64
66
  }, other, {
65
67
  ref: ref
@@ -1,5 +1,4 @@
1
- import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
- import { CurveOptions } from "./curve.types.js";
1
+ import { FunnelCurveGenerator, CurveOptions, Point } from "./curve.types.js";
3
2
  /**
4
3
  * This is a custom "bump" curve generator.
5
4
  * It draws smooth curves for the 4 provided points,
@@ -8,7 +7,7 @@ import { CurveOptions } from "./curve.types.js";
8
7
  * The implementation is based on the d3-shape bump curve generator.
9
8
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/bump.js
10
9
  */
11
- export declare class Bump implements CurveGenerator {
10
+ export declare class Bump implements FunnelCurveGenerator {
12
11
  private context;
13
12
  private isHorizontal;
14
13
  private min;
@@ -24,6 +23,7 @@ export declare class Bump implements CurveGenerator {
24
23
  areaEnd(): void;
25
24
  lineStart(): void;
26
25
  lineEnd(): void;
26
+ processPoints(points: Point[]): Point[];
27
27
  point(x: number, y: number): void;
28
28
  private drawPath;
29
29
  private drawHorizontalPath;
@@ -53,6 +53,9 @@ class Bump {
53
53
  areaEnd() {}
54
54
  lineStart() {}
55
55
  lineEnd() {}
56
+ processPoints(points) {
57
+ return points;
58
+ }
56
59
  point(x, y) {
57
60
  this.points.push({
58
61
  x,
@@ -1,3 +1,4 @@
1
+ import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
1
2
  export type CurveOptions = {
2
3
  /**
3
4
  * The gap between each segment.
@@ -44,4 +45,16 @@ export type FunnelPointShape = 'square' | 'sharp';
44
45
  export type Point = {
45
46
  x: number;
46
47
  y: number;
47
- };
48
+ };
49
+ export interface FunnelCurveGenerator extends CurveGenerator {
50
+ /**
51
+ * Processes the points to create a curve based on the provided options.
52
+ * This does not draw the curve but prepares the points for rendering.
53
+ *
54
+ * @param points The points to process.
55
+ * @param options The options for the curve.
56
+ * @returns The processed points.
57
+ */
58
+ processPoints(points: Point[], xPosition: PositionGetter, yPosition: PositionGetter): Point[];
59
+ }
60
+ export type PositionGetter = (value: number, bandIndex: number, bandIdentifier: string | number, stackOffset?: number, useBand?: boolean) => number;
@@ -1,3 +1,8 @@
1
- import { CurveFactory } from '@mui/x-charts-vendor/d3-shape';
1
+ import type { Path } from '@mui/x-charts-vendor/d3-path';
2
2
  import { CurveOptions, FunnelCurveType } from "./curve.types.js";
3
- export declare const getFunnelCurve: (curve: FunnelCurveType | undefined, options: CurveOptions) => CurveFactory;
3
+ import { Step } from "./step.js";
4
+ import { Linear } from "./linear.js";
5
+ import { Bump } from "./bump.js";
6
+ import { Pyramid } from "./pyramid.js";
7
+ import { StepPyramid } from "./step-pyramid.js";
8
+ export declare const getFunnelCurve: (curve: FunnelCurveType | undefined, options: CurveOptions) => (context: CanvasRenderingContext2D | Path) => Step | Linear | Bump | Pyramid | StepPyramid;
@@ -1,5 +1,4 @@
1
- import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
- import { CurveOptions } from "./curve.types.js";
1
+ import { FunnelCurveGenerator, CurveOptions, Point } from "./curve.types.js";
3
2
  /**
4
3
  * This is a custom "linear" curve generator.
5
4
  * It draws straight lines for the 4 provided points,
@@ -8,7 +7,7 @@ import { CurveOptions } from "./curve.types.js";
8
7
  * The implementation is based on the d3-shape linear curve generator.
9
8
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/linear.js
10
9
  */
11
- export declare class Linear implements CurveGenerator {
10
+ export declare class Linear implements FunnelCurveGenerator {
12
11
  private context;
13
12
  private position;
14
13
  private sections;
@@ -36,5 +35,6 @@ export declare class Linear implements CurveGenerator {
36
35
  lineStart(): void;
37
36
  lineEnd(): void;
38
37
  protected getBorderRadius(): number | number[];
38
+ processPoints(points: Point[]): Point[];
39
39
  point(xIn: number, yIn: number): void;
40
40
  }
@@ -97,7 +97,7 @@ class Linear {
97
97
  }
98
98
  // Is smallest section and shaped like a triangle
99
99
  if (this.position === this.sections - 1 && this.pointShape === 'sharp') {
100
- return [this.borderRadius];
100
+ return [0, 0, this.borderRadius];
101
101
  }
102
102
 
103
103
  // Is smallest section
@@ -107,19 +107,11 @@ class Linear {
107
107
  }
108
108
  return 0;
109
109
  }
110
- point(xIn, yIn) {
111
- this.points.push({
112
- x: xIn,
113
- y: yIn
114
- });
115
- if (this.points.length < 4) {
116
- return;
117
- }
118
-
110
+ processPoints(points) {
119
111
  // Add gaps where they are needed.
120
- this.points = this.points.map((point, index) => {
121
- const slopeStart = this.points.at(index <= 1 ? 0 : 3);
122
- const slopeEnd = this.points.at(index <= 1 ? 1 : 2);
112
+ const processedPoints = points.map((point, index) => {
113
+ const slopeStart = points.at(index <= 1 ? 0 : 3);
114
+ const slopeEnd = points.at(index <= 1 ? 1 : 2);
123
115
  if (this.isHorizontal) {
124
116
  const yGetter = (0, _utils.lerpY)(slopeStart.x - this.gap, slopeStart.y, slopeEnd.x, slopeEnd.y);
125
117
  return {
@@ -141,15 +133,15 @@ class Linear {
141
133
  let firstPoint = null;
142
134
  let secondPoint = null;
143
135
  if (isFirstSection && this.isIncreasing) {
144
- firstPoint = this.points[1];
145
- secondPoint = this.points[2];
136
+ firstPoint = processedPoints[1];
137
+ secondPoint = processedPoints[2];
146
138
  }
147
139
  if (isLastSection && !this.isIncreasing) {
148
- firstPoint = this.points[3];
149
- secondPoint = this.points[0];
140
+ firstPoint = processedPoints[3];
141
+ secondPoint = processedPoints[0];
150
142
  }
151
143
  if (firstPoint && secondPoint) {
152
- this.points = [
144
+ return [
153
145
  // Sharp point at the start
154
146
  this.isHorizontal ? {
155
147
  x: this.max.x,
@@ -162,6 +154,19 @@ class Linear {
162
154
  firstPoint, secondPoint];
163
155
  }
164
156
  }
157
+ return processedPoints;
158
+ }
159
+ point(xIn, yIn) {
160
+ this.points.push({
161
+ x: xIn,
162
+ y: yIn
163
+ });
164
+ const isLastSection = this.position === this.sections - 1;
165
+ const isFirstSection = this.position === 0;
166
+ const isSharpPoint = this.pointShape === 'sharp' && (isLastSection && !this.isIncreasing || isFirstSection && this.isIncreasing);
167
+ if (this.points.length < (isSharpPoint ? 3 : 4)) {
168
+ return;
169
+ }
165
170
  (0, _borderRadiusPolygon.borderRadiusPolygon)(this.context, this.points, this.getBorderRadius());
166
171
  }
167
172
  }