@mui/x-charts-pro 7.0.0-alpha.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 (190) hide show
  1. package/BarChartPro/BarChartPro.d.ts +18 -0
  2. package/BarChartPro/BarChartPro.js +417 -0
  3. package/BarChartPro/index.d.ts +1 -0
  4. package/BarChartPro/index.js +1 -0
  5. package/BarChartPro/package.json +6 -0
  6. package/CHANGELOG.md +4404 -0
  7. package/ChartContainerPro/ChartContainerPro.d.ts +7 -0
  8. package/ChartContainerPro/ChartContainerPro.js +282 -0
  9. package/ChartContainerPro/index.d.ts +1 -0
  10. package/ChartContainerPro/index.js +1 -0
  11. package/ChartContainerPro/package.json +6 -0
  12. package/ChartContainerPro/useChartContainerProProps.d.ts +15 -0
  13. package/ChartContainerPro/useChartContainerProProps.js +39 -0
  14. package/Heatmap/DefaultHeatmapTooltip.d.ts +7 -0
  15. package/Heatmap/DefaultHeatmapTooltip.js +97 -0
  16. package/Heatmap/Heatmap.d.ts +49 -0
  17. package/Heatmap/Heatmap.js +387 -0
  18. package/Heatmap/HeatmapItem.d.ts +49 -0
  19. package/Heatmap/HeatmapItem.js +106 -0
  20. package/Heatmap/HeatmapPlot.d.ts +9 -0
  21. package/Heatmap/HeatmapPlot.js +57 -0
  22. package/Heatmap/extremums.d.ts +2 -0
  23. package/Heatmap/extremums.js +8 -0
  24. package/Heatmap/formatter.d.ts +3 -0
  25. package/Heatmap/formatter.js +20 -0
  26. package/Heatmap/getColor.d.ts +3 -0
  27. package/Heatmap/getColor.js +15 -0
  28. package/Heatmap/heatmapClasses.d.ts +11 -0
  29. package/Heatmap/heatmapClasses.js +13 -0
  30. package/Heatmap/index.d.ts +4 -0
  31. package/Heatmap/index.js +4 -0
  32. package/Heatmap/package.json +6 -0
  33. package/Heatmap/plugin.d.ts +2 -0
  34. package/Heatmap/plugin.js +10 -0
  35. package/LICENSE +11 -0
  36. package/LineChartPro/LineChartPro.d.ts +17 -0
  37. package/LineChartPro/LineChartPro.js +473 -0
  38. package/LineChartPro/index.d.ts +1 -0
  39. package/LineChartPro/index.js +1 -0
  40. package/LineChartPro/package.json +6 -0
  41. package/README.md +26 -0
  42. package/ResponsiveChartContainerPro/ResponsiveChartContainerPro.d.ts +7 -0
  43. package/ResponsiveChartContainerPro/ResponsiveChartContainerPro.js +259 -0
  44. package/ResponsiveChartContainerPro/index.d.ts +1 -0
  45. package/ResponsiveChartContainerPro/index.js +1 -0
  46. package/ResponsiveChartContainerPro/package.json +6 -0
  47. package/ResponsiveChartContainerPro/useResponsiveChartContainerProProps.d.ts +41 -0
  48. package/ResponsiveChartContainerPro/useResponsiveChartContainerProProps.js +25 -0
  49. package/ScatterChartPro/ScatterChartPro.d.ts +17 -0
  50. package/ScatterChartPro/ScatterChartPro.js +388 -0
  51. package/ScatterChartPro/index.d.ts +1 -0
  52. package/ScatterChartPro/index.js +1 -0
  53. package/ScatterChartPro/package.json +6 -0
  54. package/context/CartesianProviderPro/CartesianProviderPro.d.ts +6 -0
  55. package/context/CartesianProviderPro/CartesianProviderPro.js +54 -0
  56. package/context/CartesianProviderPro/index.d.ts +1 -0
  57. package/context/CartesianProviderPro/index.js +1 -0
  58. package/context/ZoomProvider/Zoom.types.d.ts +134 -0
  59. package/context/ZoomProvider/Zoom.types.js +1 -0
  60. package/context/ZoomProvider/ZoomContext.d.ts +4 -0
  61. package/context/ZoomProvider/ZoomContext.js +16 -0
  62. package/context/ZoomProvider/ZoomProvider.d.ts +3 -0
  63. package/context/ZoomProvider/ZoomProvider.js +53 -0
  64. package/context/ZoomProvider/ZoomSetup.d.ts +9 -0
  65. package/context/ZoomProvider/ZoomSetup.js +16 -0
  66. package/context/ZoomProvider/defaultizeZoom.d.ts +2 -0
  67. package/context/ZoomProvider/defaultizeZoom.js +31 -0
  68. package/context/ZoomProvider/index.d.ts +3 -0
  69. package/context/ZoomProvider/index.js +3 -0
  70. package/context/ZoomProvider/initializeZoomData.d.ts +6 -0
  71. package/context/ZoomProvider/initializeZoomData.js +13 -0
  72. package/context/ZoomProvider/useSetupPan.d.ts +1 -0
  73. package/context/ZoomProvider/useSetupPan.js +104 -0
  74. package/context/ZoomProvider/useSetupZoom.d.ts +1 -0
  75. package/context/ZoomProvider/useSetupZoom.js +272 -0
  76. package/context/ZoomProvider/useZoom.d.ts +7 -0
  77. package/context/ZoomProvider/useZoom.js +17 -0
  78. package/context/index.d.ts +3 -0
  79. package/context/index.js +5 -0
  80. package/context/package.json +6 -0
  81. package/hooks/index.d.ts +1 -0
  82. package/hooks/index.js +1 -0
  83. package/hooks/package.json +6 -0
  84. package/hooks/useSeries.d.ts +11 -0
  85. package/hooks/useSeries.js +14 -0
  86. package/index.d.ts +31 -0
  87. package/index.js +45 -0
  88. package/internals/utils/releaseInfo.d.ts +1 -0
  89. package/internals/utils/releaseInfo.js +13 -0
  90. package/models/index.d.ts +1 -0
  91. package/models/index.js +1 -0
  92. package/models/package.json +6 -0
  93. package/models/seriesType/heatmap.d.ts +28 -0
  94. package/models/seriesType/heatmap.js +1 -0
  95. package/models/seriesType/index.d.ts +1 -0
  96. package/models/seriesType/index.js +1 -0
  97. package/modern/BarChartPro/BarChartPro.js +417 -0
  98. package/modern/BarChartPro/index.js +1 -0
  99. package/modern/ChartContainerPro/ChartContainerPro.js +282 -0
  100. package/modern/ChartContainerPro/index.js +1 -0
  101. package/modern/ChartContainerPro/useChartContainerProProps.js +39 -0
  102. package/modern/Heatmap/DefaultHeatmapTooltip.js +97 -0
  103. package/modern/Heatmap/Heatmap.js +387 -0
  104. package/modern/Heatmap/HeatmapItem.js +106 -0
  105. package/modern/Heatmap/HeatmapPlot.js +57 -0
  106. package/modern/Heatmap/extremums.js +8 -0
  107. package/modern/Heatmap/formatter.js +20 -0
  108. package/modern/Heatmap/getColor.js +15 -0
  109. package/modern/Heatmap/heatmapClasses.js +13 -0
  110. package/modern/Heatmap/index.js +4 -0
  111. package/modern/Heatmap/plugin.js +10 -0
  112. package/modern/LineChartPro/LineChartPro.js +473 -0
  113. package/modern/LineChartPro/index.js +1 -0
  114. package/modern/ResponsiveChartContainerPro/ResponsiveChartContainerPro.js +259 -0
  115. package/modern/ResponsiveChartContainerPro/index.js +1 -0
  116. package/modern/ResponsiveChartContainerPro/useResponsiveChartContainerProProps.js +25 -0
  117. package/modern/ScatterChartPro/ScatterChartPro.js +388 -0
  118. package/modern/ScatterChartPro/index.js +1 -0
  119. package/modern/context/CartesianProviderPro/CartesianProviderPro.js +54 -0
  120. package/modern/context/CartesianProviderPro/index.js +1 -0
  121. package/modern/context/ZoomProvider/Zoom.types.js +1 -0
  122. package/modern/context/ZoomProvider/ZoomContext.js +16 -0
  123. package/modern/context/ZoomProvider/ZoomProvider.js +53 -0
  124. package/modern/context/ZoomProvider/ZoomSetup.js +16 -0
  125. package/modern/context/ZoomProvider/defaultizeZoom.js +31 -0
  126. package/modern/context/ZoomProvider/index.js +3 -0
  127. package/modern/context/ZoomProvider/initializeZoomData.js +13 -0
  128. package/modern/context/ZoomProvider/useSetupPan.js +104 -0
  129. package/modern/context/ZoomProvider/useSetupZoom.js +272 -0
  130. package/modern/context/ZoomProvider/useZoom.js +17 -0
  131. package/modern/context/index.js +5 -0
  132. package/modern/hooks/index.js +1 -0
  133. package/modern/hooks/useSeries.js +14 -0
  134. package/modern/index.js +45 -0
  135. package/modern/internals/utils/releaseInfo.js +13 -0
  136. package/modern/models/index.js +1 -0
  137. package/modern/models/seriesType/heatmap.js +1 -0
  138. package/modern/models/seriesType/index.js +1 -0
  139. package/modern/typeOverloads/index.js +1 -0
  140. package/modern/typeOverloads/modules.js +1 -0
  141. package/node/BarChartPro/BarChartPro.js +425 -0
  142. package/node/BarChartPro/index.js +16 -0
  143. package/node/ChartContainerPro/ChartContainerPro.js +290 -0
  144. package/node/ChartContainerPro/index.js +16 -0
  145. package/node/ChartContainerPro/useChartContainerProProps.js +47 -0
  146. package/node/Heatmap/DefaultHeatmapTooltip.js +105 -0
  147. package/node/Heatmap/Heatmap.js +395 -0
  148. package/node/Heatmap/HeatmapItem.js +114 -0
  149. package/node/Heatmap/HeatmapPlot.js +65 -0
  150. package/node/Heatmap/extremums.js +15 -0
  151. package/node/Heatmap/formatter.js +27 -0
  152. package/node/Heatmap/getColor.js +21 -0
  153. package/node/Heatmap/heatmapClasses.js +21 -0
  154. package/node/Heatmap/index.js +47 -0
  155. package/node/Heatmap/plugin.js +17 -0
  156. package/node/LineChartPro/LineChartPro.js +481 -0
  157. package/node/LineChartPro/index.js +16 -0
  158. package/node/ResponsiveChartContainerPro/ResponsiveChartContainerPro.js +267 -0
  159. package/node/ResponsiveChartContainerPro/index.js +16 -0
  160. package/node/ResponsiveChartContainerPro/useResponsiveChartContainerProProps.js +33 -0
  161. package/node/ScatterChartPro/ScatterChartPro.js +396 -0
  162. package/node/ScatterChartPro/index.js +16 -0
  163. package/node/context/CartesianProviderPro/CartesianProviderPro.js +61 -0
  164. package/node/context/CartesianProviderPro/index.js +16 -0
  165. package/node/context/ZoomProvider/Zoom.types.js +5 -0
  166. package/node/context/ZoomProvider/ZoomContext.js +24 -0
  167. package/node/context/ZoomProvider/ZoomProvider.js +62 -0
  168. package/node/context/ZoomProvider/ZoomSetup.js +20 -0
  169. package/node/context/ZoomProvider/defaultizeZoom.js +39 -0
  170. package/node/context/ZoomProvider/index.js +38 -0
  171. package/node/context/ZoomProvider/initializeZoomData.js +20 -0
  172. package/node/context/ZoomProvider/useSetupPan.js +114 -0
  173. package/node/context/ZoomProvider/useSetupZoom.js +281 -0
  174. package/node/context/ZoomProvider/useZoom.js +25 -0
  175. package/node/context/index.js +27 -0
  176. package/node/hooks/index.js +12 -0
  177. package/node/hooks/useSeries.js +21 -0
  178. package/node/index.js +354 -0
  179. package/node/internals/utils/releaseInfo.js +20 -0
  180. package/node/models/index.js +16 -0
  181. package/node/models/seriesType/heatmap.js +5 -0
  182. package/node/models/seriesType/index.js +16 -0
  183. package/node/typeOverloads/index.js +6 -0
  184. package/node/typeOverloads/modules.js +5 -0
  185. package/package.json +64 -0
  186. package/typeOverloads/index.d.ts +1 -0
  187. package/typeOverloads/index.js +1 -0
  188. package/typeOverloads/modules.d.ts +17 -0
  189. package/typeOverloads/modules.js +1 -0
  190. package/typeOverloads/package.json +6 -0
@@ -0,0 +1,54 @@
1
+ import * as React from 'react';
2
+ import { useDrawingArea, useSeries, CartesianContext, cartesianProviderUtils, useXExtremumGetter, useYExtremumGetter } from '@mui/x-charts/internals';
3
+ import { useZoom } from '../ZoomProvider/useZoom';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ const {
6
+ computeValue
7
+ } = cartesianProviderUtils;
8
+ function CartesianContextProviderPro(props) {
9
+ const {
10
+ xAxis,
11
+ yAxis,
12
+ dataset,
13
+ children
14
+ } = props;
15
+ const formattedSeries = useSeries();
16
+ const drawingArea = useDrawingArea();
17
+ const {
18
+ zoomData
19
+ } = useZoom();
20
+ const xExtremumGetters = useXExtremumGetter();
21
+ const yExtremumGetters = useYExtremumGetter();
22
+ const xValues = React.useMemo(() => computeValue({
23
+ drawingArea,
24
+ formattedSeries,
25
+ axis: xAxis,
26
+ extremumGetters: xExtremumGetters,
27
+ dataset,
28
+ axisDirection: 'x',
29
+ zoomData
30
+ }), [drawingArea, formattedSeries, xAxis, xExtremumGetters, dataset, zoomData]);
31
+ const yValues = React.useMemo(() => computeValue({
32
+ drawingArea,
33
+ formattedSeries,
34
+ axis: yAxis,
35
+ extremumGetters: yExtremumGetters,
36
+ dataset,
37
+ axisDirection: 'y',
38
+ zoomData
39
+ }), [drawingArea, formattedSeries, yAxis, yExtremumGetters, dataset, zoomData]);
40
+ const value = React.useMemo(() => ({
41
+ isInitialized: true,
42
+ data: {
43
+ xAxis: xValues.axis,
44
+ yAxis: yValues.axis,
45
+ xAxisIds: xValues.axisIds,
46
+ yAxisIds: yValues.axisIds
47
+ }
48
+ }), [xValues, yValues]);
49
+ return /*#__PURE__*/_jsx(CartesianContext.Provider, {
50
+ value: value,
51
+ children: children
52
+ });
53
+ }
54
+ export { CartesianContextProviderPro };
@@ -0,0 +1 @@
1
+ export * from './CartesianProviderPro';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ export const ZoomContext = /*#__PURE__*/React.createContext({
3
+ isInitialized: false,
4
+ data: {
5
+ isZoomEnabled: false,
6
+ isPanEnabled: false,
7
+ options: {},
8
+ zoomData: [],
9
+ setZoomData: () => {},
10
+ isInteracting: false,
11
+ setIsInteracting: () => {}
12
+ }
13
+ });
14
+ if (process.env.NODE_ENV !== 'production') {
15
+ ZoomContext.displayName = 'ZoomContext';
16
+ }
@@ -0,0 +1,53 @@
1
+ import * as React from 'react';
2
+ import useControlled from '@mui/utils/useControlled';
3
+ import { ZoomContext } from './ZoomContext';
4
+ import { defaultizeZoom } from './defaultizeZoom';
5
+ import { initializeZoomData } from './initializeZoomData';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ export function ZoomProvider({
8
+ children,
9
+ xAxis,
10
+ yAxis,
11
+ zoom,
12
+ onZoomChange
13
+ }) {
14
+ const [isInteracting, setIsInteracting] = React.useState(false);
15
+ const options = React.useMemo(() => [...defaultizeZoom(xAxis, 'x'), ...defaultizeZoom(yAxis, 'y')].reduce((acc, v) => {
16
+ acc[v.axisId] = v;
17
+ return acc;
18
+ }, {}), [xAxis, yAxis]);
19
+
20
+ // Default zoom data is initialized only once when uncontrolled. If the user changes the options
21
+ // after the initial render, the zoom data will not be updated until the next zoom interaction.
22
+ // This is required to avoid warnings about controlled/uncontrolled components.
23
+ const defaultZoomData = React.useRef(initializeZoomData(options));
24
+ const [zoomData, setZoomData] = useControlled({
25
+ controlled: zoom,
26
+ default: defaultZoomData.current,
27
+ name: 'ZoomProvider',
28
+ state: 'zoom'
29
+ });
30
+ const setZoomDataCallback = React.useCallback(newZoomData => {
31
+ setZoomData(newZoomData);
32
+ onZoomChange?.(newZoomData);
33
+ }, [setZoomData, onZoomChange]);
34
+ const value = React.useMemo(() => ({
35
+ isInitialized: true,
36
+ data: {
37
+ isZoomEnabled: Object.keys(options).length > 0,
38
+ isPanEnabled: isPanEnabled(options),
39
+ options,
40
+ zoomData,
41
+ setZoomData: setZoomDataCallback,
42
+ isInteracting,
43
+ setIsInteracting
44
+ }
45
+ }), [zoomData, isInteracting, setIsInteracting, options, setZoomDataCallback]);
46
+ return /*#__PURE__*/_jsx(ZoomContext.Provider, {
47
+ value: value,
48
+ children: children
49
+ });
50
+ }
51
+ function isPanEnabled(options) {
52
+ return Object.values(options).some(v => v.panning) || false;
53
+ }
@@ -0,0 +1,16 @@
1
+ import { useSetupPan } from './useSetupPan';
2
+ import { useSetupZoom } from './useSetupZoom';
3
+
4
+ /**
5
+ * Sets up the zoom functionality if using composition or a custom chart.
6
+ *
7
+ * Simply add this component at the same level as the chart component to enable zooming and panning.
8
+ *
9
+ * See: [Composition](https://mui.com/x/react-charts/composition/)
10
+ */
11
+ function ZoomSetup() {
12
+ useSetupZoom();
13
+ useSetupPan();
14
+ return null;
15
+ }
16
+ export { ZoomSetup };
@@ -0,0 +1,31 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import { isDefined } from '@mui/x-charts/internals';
3
+ const defaultZoomOptions = {
4
+ minStart: 0,
5
+ maxEnd: 100,
6
+ step: 5,
7
+ minSpan: 10,
8
+ maxSpan: 100,
9
+ panning: true
10
+ };
11
+ export const defaultizeZoom = (axis, axisDirection) => {
12
+ if (!axis) {
13
+ return [];
14
+ }
15
+ const defaultized = axis.map(v => {
16
+ if (!v.zoom) {
17
+ return undefined;
18
+ }
19
+ if (v.zoom === true) {
20
+ return _extends({
21
+ axisId: v.id,
22
+ axisDirection
23
+ }, defaultZoomOptions);
24
+ }
25
+ return _extends({
26
+ axisId: v.id,
27
+ axisDirection
28
+ }, defaultZoomOptions, v.zoom);
29
+ }).filter(isDefined);
30
+ return defaultized;
31
+ };
@@ -0,0 +1,3 @@
1
+ export * from './ZoomContext';
2
+ export * from './ZoomProvider';
3
+ export * from './Zoom.types';
@@ -0,0 +1,13 @@
1
+ // This function is used to initialize the zoom data when it is not provided by the user.
2
+ // It is helpful to avoid the need to provide the possibly auto-generated id for each axis.
3
+ export const initializeZoomData = options => {
4
+ return Object.values(options).map(({
5
+ axisId,
6
+ minStart: start,
7
+ maxEnd: end
8
+ }) => ({
9
+ axisId,
10
+ start,
11
+ end
12
+ }));
13
+ };
@@ -0,0 +1,104 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks';
4
+ import { getSVGPoint } from '@mui/x-charts/internals';
5
+ import { useZoom } from './useZoom';
6
+ export const useSetupPan = () => {
7
+ const {
8
+ zoomData,
9
+ setZoomData,
10
+ setIsInteracting,
11
+ isPanEnabled,
12
+ options
13
+ } = useZoom();
14
+ const drawingArea = useDrawingArea();
15
+ const svgRef = useSvgRef();
16
+ const isDraggingRef = React.useRef(false);
17
+ const touchStartRef = React.useRef(null);
18
+ const eventCacheRef = React.useRef([]);
19
+ React.useEffect(() => {
20
+ const element = svgRef.current;
21
+ if (element === null || !isPanEnabled) {
22
+ return () => {};
23
+ }
24
+ const handlePan = event => {
25
+ if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) {
26
+ return;
27
+ }
28
+ if (touchStartRef.current == null) {
29
+ return;
30
+ }
31
+ const point = getSVGPoint(element, event);
32
+ const movementX = point.x - touchStartRef.current.x;
33
+ const movementY = (point.y - touchStartRef.current.y) * -1;
34
+ const newZoomData = touchStartRef.current.zoomData.map(zoom => {
35
+ const option = options[zoom.axisId];
36
+ if (!option || !option.panning) {
37
+ return zoom;
38
+ }
39
+ const min = zoom.start;
40
+ const max = zoom.end;
41
+ const span = max - min;
42
+ const MIN_PERCENT = option.minStart;
43
+ const MAX_PERCENT = option.maxEnd;
44
+ const movement = option.axisDirection === 'x' ? movementX : movementY;
45
+ const dimension = option.axisDirection === 'x' ? drawingArea.width : drawingArea.height;
46
+ let newMinPercent = min - movement / dimension * span;
47
+ let newMaxPercent = max - movement / dimension * span;
48
+ if (newMinPercent < MIN_PERCENT) {
49
+ newMinPercent = MIN_PERCENT;
50
+ newMaxPercent = newMinPercent + span;
51
+ }
52
+ if (newMaxPercent > MAX_PERCENT) {
53
+ newMaxPercent = MAX_PERCENT;
54
+ newMinPercent = newMaxPercent - span;
55
+ }
56
+ if (newMinPercent < MIN_PERCENT || newMaxPercent > MAX_PERCENT || span < option.minSpan || span > option.maxSpan) {
57
+ return zoom;
58
+ }
59
+ return _extends({}, zoom, {
60
+ start: newMinPercent,
61
+ end: newMaxPercent
62
+ });
63
+ });
64
+ setZoomData(newZoomData);
65
+ };
66
+ const handleDown = event => {
67
+ eventCacheRef.current.push(event);
68
+ const point = getSVGPoint(element, event);
69
+ if (!drawingArea.isPointInside(point)) {
70
+ return;
71
+ }
72
+
73
+ // If there is only one pointer, prevent selecting text
74
+ if (eventCacheRef.current.length === 1) {
75
+ event.preventDefault();
76
+ }
77
+ isDraggingRef.current = true;
78
+ setIsInteracting(true);
79
+ touchStartRef.current = {
80
+ x: point.x,
81
+ y: point.y,
82
+ zoomData
83
+ };
84
+ };
85
+ const handleUp = event => {
86
+ eventCacheRef.current.splice(eventCacheRef.current.findIndex(e => e.pointerId === event.pointerId), 1);
87
+ setIsInteracting(false);
88
+ isDraggingRef.current = false;
89
+ touchStartRef.current = null;
90
+ };
91
+ element.addEventListener('pointerdown', handleDown);
92
+ document.addEventListener('pointermove', handlePan);
93
+ document.addEventListener('pointerup', handleUp);
94
+ document.addEventListener('pointercancel', handleUp);
95
+ document.addEventListener('pointerleave', handleUp);
96
+ return () => {
97
+ element.removeEventListener('pointerdown', handleDown);
98
+ document.removeEventListener('pointermove', handlePan);
99
+ document.removeEventListener('pointerup', handleUp);
100
+ document.removeEventListener('pointercancel', handleUp);
101
+ document.removeEventListener('pointerleave', handleUp);
102
+ };
103
+ }, [drawingArea, svgRef, isDraggingRef, setIsInteracting, zoomData, setZoomData, isPanEnabled, options]);
104
+ };
@@ -0,0 +1,272 @@
1
+ import * as React from 'react';
2
+ import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks';
3
+ import { getSVGPoint } from '@mui/x-charts/internals';
4
+ import { useZoom } from './useZoom';
5
+ /**
6
+ * Helper to get the range (in percents of a reference range) corresponding to a given scale.
7
+ * @param centerRatio {number} The ratio of the point that should not move between the previous and next range.
8
+ * @param scaleRatio {number} The target scale ratio.
9
+ * @returns The range to display.
10
+ */
11
+ const zoomAtPoint = (centerRatio, scaleRatio, currentZoomData, options) => {
12
+ const MIN_RANGE = options.minStart;
13
+ const MAX_RANGE = options.maxEnd;
14
+ const MIN_ALLOWED_SPAN = options.minSpan;
15
+ const minRange = currentZoomData.start;
16
+ const maxRange = currentZoomData.end;
17
+ const point = minRange + centerRatio * (maxRange - minRange);
18
+ let newMinRange = (minRange + point * (scaleRatio - 1)) / scaleRatio;
19
+ let newMaxRange = (maxRange + point * (scaleRatio - 1)) / scaleRatio;
20
+ let minSpillover = 0;
21
+ let maxSpillover = 0;
22
+ if (newMinRange < MIN_RANGE) {
23
+ minSpillover = Math.abs(newMinRange);
24
+ newMinRange = MIN_RANGE;
25
+ }
26
+ if (newMaxRange > MAX_RANGE) {
27
+ maxSpillover = Math.abs(newMaxRange - MAX_RANGE);
28
+ newMaxRange = MAX_RANGE;
29
+ }
30
+ if (minSpillover > 0 && maxSpillover > 0) {
31
+ return [MIN_RANGE, MAX_RANGE];
32
+ }
33
+ newMaxRange += minSpillover;
34
+ newMinRange -= maxSpillover;
35
+ newMinRange = Math.min(MAX_RANGE - MIN_ALLOWED_SPAN, Math.max(MIN_RANGE, newMinRange));
36
+ newMaxRange = Math.max(MIN_ALLOWED_SPAN, Math.min(MAX_RANGE, newMaxRange));
37
+ return [newMinRange, newMaxRange];
38
+ };
39
+ export const useSetupZoom = () => {
40
+ const {
41
+ setZoomData,
42
+ isZoomEnabled,
43
+ options,
44
+ setIsInteracting
45
+ } = useZoom();
46
+ const drawingArea = useDrawingArea();
47
+ const svgRef = useSvgRef();
48
+ const eventCacheRef = React.useRef([]);
49
+ const eventPrevDiff = React.useRef(0);
50
+ const interactionTimeoutRef = React.useRef(undefined);
51
+ React.useEffect(() => {
52
+ const element = svgRef.current;
53
+ if (element === null || !isZoomEnabled) {
54
+ return () => {};
55
+ }
56
+ const wheelHandler = event => {
57
+ if (element === null) {
58
+ return;
59
+ }
60
+ const point = getSVGPoint(element, event);
61
+ if (!drawingArea.isPointInside(point)) {
62
+ return;
63
+ }
64
+ event.preventDefault();
65
+ if (interactionTimeoutRef.current) {
66
+ clearTimeout(interactionTimeoutRef.current);
67
+ }
68
+ setIsInteracting(true);
69
+ // Debounce transition to `isInteractive=false`.
70
+ // Useful because wheel events don't have an "end" event.
71
+ interactionTimeoutRef.current = window.setTimeout(() => {
72
+ setIsInteracting(false);
73
+ }, 166);
74
+ setZoomData(prevZoomData => {
75
+ return prevZoomData.map(zoom => {
76
+ const option = options[zoom.axisId];
77
+ if (!option) {
78
+ return zoom;
79
+ }
80
+ const centerRatio = option.axisDirection === 'x' ? getHorizontalCenterRatio(point, drawingArea) : getVerticalCenterRatio(point, drawingArea);
81
+ const {
82
+ scaleRatio,
83
+ isZoomIn
84
+ } = getWheelScaleRatio(event, option.step);
85
+ const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option);
86
+ if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) {
87
+ return zoom;
88
+ }
89
+ return {
90
+ axisId: zoom.axisId,
91
+ start: newMinRange,
92
+ end: newMaxRange
93
+ };
94
+ });
95
+ });
96
+ };
97
+ function pointerDownHandler(event) {
98
+ eventCacheRef.current.push(event);
99
+ setIsInteracting(true);
100
+ }
101
+ function pointerMoveHandler(event) {
102
+ if (element === null) {
103
+ return;
104
+ }
105
+ const index = eventCacheRef.current.findIndex(cachedEv => cachedEv.pointerId === event.pointerId);
106
+ eventCacheRef.current[index] = event;
107
+
108
+ // Not a pinch gesture
109
+ if (eventCacheRef.current.length !== 2) {
110
+ return;
111
+ }
112
+ const firstEvent = eventCacheRef.current[0];
113
+ const curDiff = getDiff(eventCacheRef.current);
114
+ setZoomData(prevZoomData => {
115
+ const newZoomData = prevZoomData.map(zoom => {
116
+ const option = options[zoom.axisId];
117
+ if (!option) {
118
+ return zoom;
119
+ }
120
+ const {
121
+ scaleRatio,
122
+ isZoomIn
123
+ } = getPinchScaleRatio(curDiff, eventPrevDiff.current, option.step);
124
+
125
+ // If the scale ratio is 0, it means the pinch gesture is not valid.
126
+ if (scaleRatio === 0) {
127
+ return zoom;
128
+ }
129
+ const point = getSVGPoint(element, firstEvent);
130
+ const centerRatio = option.axisDirection === 'x' ? getHorizontalCenterRatio(point, drawingArea) : getVerticalCenterRatio(point, drawingArea);
131
+ const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option);
132
+ if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) {
133
+ return zoom;
134
+ }
135
+ return {
136
+ axisId: zoom.axisId,
137
+ start: newMinRange,
138
+ end: newMaxRange
139
+ };
140
+ });
141
+ eventPrevDiff.current = curDiff;
142
+ return newZoomData;
143
+ });
144
+ }
145
+ function pointerUpHandler(event) {
146
+ eventCacheRef.current.splice(eventCacheRef.current.findIndex(e => e.pointerId === event.pointerId), 1);
147
+ if (eventCacheRef.current.length < 2) {
148
+ eventPrevDiff.current = 0;
149
+ }
150
+ if (event.type === 'pointerup' || event.type === 'pointercancel') {
151
+ setIsInteracting(false);
152
+ }
153
+ }
154
+ element.addEventListener('wheel', wheelHandler);
155
+ element.addEventListener('pointerdown', pointerDownHandler);
156
+ element.addEventListener('pointermove', pointerMoveHandler);
157
+ element.addEventListener('pointerup', pointerUpHandler);
158
+ element.addEventListener('pointercancel', pointerUpHandler);
159
+ element.addEventListener('pointerout', pointerUpHandler);
160
+ element.addEventListener('pointerleave', pointerUpHandler);
161
+
162
+ // Prevent zooming the entire page on touch devices
163
+ element.addEventListener('touchstart', preventDefault);
164
+ element.addEventListener('touchmove', preventDefault);
165
+ return () => {
166
+ element.removeEventListener('wheel', wheelHandler);
167
+ element.removeEventListener('pointerdown', pointerDownHandler);
168
+ element.removeEventListener('pointermove', pointerMoveHandler);
169
+ element.removeEventListener('pointerup', pointerUpHandler);
170
+ element.removeEventListener('pointercancel', pointerUpHandler);
171
+ element.removeEventListener('pointerout', pointerUpHandler);
172
+ element.removeEventListener('pointerleave', pointerUpHandler);
173
+ element.removeEventListener('touchstart', preventDefault);
174
+ element.removeEventListener('touchmove', preventDefault);
175
+ if (interactionTimeoutRef.current) {
176
+ clearTimeout(interactionTimeoutRef.current);
177
+ }
178
+ };
179
+ }, [svgRef, setZoomData, drawingArea, isZoomEnabled, options, setIsInteracting]);
180
+ };
181
+
182
+ /**
183
+ * Checks if the new span is valid.
184
+ */
185
+ function isSpanValid(minRange, maxRange, isZoomIn, option) {
186
+ const newSpanPercent = maxRange - minRange;
187
+ if (isZoomIn && newSpanPercent < option.minSpan || !isZoomIn && newSpanPercent > option.maxSpan) {
188
+ return false;
189
+ }
190
+ if (minRange < option.minStart || maxRange > option.maxEnd) {
191
+ return false;
192
+ }
193
+ return true;
194
+ }
195
+ function getMultiplier(event) {
196
+ const ctrlMultiplier = event.ctrlKey ? 3 : 1;
197
+
198
+ // DeltaMode: 0 is pixel, 1 is line, 2 is page
199
+ // This is defined by the browser.
200
+ if (event.deltaMode === 1) {
201
+ return 1 * ctrlMultiplier;
202
+ }
203
+ if (event.deltaMode) {
204
+ return 10 * ctrlMultiplier;
205
+ }
206
+ return 0.2 * ctrlMultiplier;
207
+ }
208
+
209
+ /**
210
+ * Get the scale ratio and if it's a zoom in or out from a wheel event.
211
+ */
212
+ function getWheelScaleRatio(event, step) {
213
+ const deltaY = -event.deltaY;
214
+ const multiplier = getMultiplier(event);
215
+ const scaledStep = step * multiplier * deltaY / 1000;
216
+ // Clamp the scale ratio between 0.1 and 1.9 so that the zoom is not too big or too small.
217
+ const scaleRatio = Math.min(Math.max(1 + scaledStep, 0.1), 1.9);
218
+ const isZoomIn = deltaY > 0;
219
+ return {
220
+ scaleRatio,
221
+ isZoomIn
222
+ };
223
+ }
224
+
225
+ /**
226
+ * Get the scale ratio and if it's a zoom in or out from a pinch gesture.
227
+ */
228
+ function getPinchScaleRatio(curDiff, prevDiff, step) {
229
+ const scaledStep = step / 1000;
230
+ let scaleRatio = 0;
231
+ let isZoomIn = false;
232
+ const hasMoved = prevDiff > 0;
233
+ if (hasMoved && curDiff > prevDiff) {
234
+ // The distance between the two pointers has increased
235
+ scaleRatio = 1 + scaledStep;
236
+ isZoomIn = true;
237
+ }
238
+ if (hasMoved && curDiff < prevDiff) {
239
+ // The distance between the two pointers has decreased
240
+ scaleRatio = 1 - scaledStep;
241
+ isZoomIn = false;
242
+ }
243
+ return {
244
+ scaleRatio,
245
+ isZoomIn
246
+ };
247
+ }
248
+ function getDiff(eventCache) {
249
+ const [firstEvent, secondEvent] = eventCache;
250
+ return Math.hypot(firstEvent.pageX - secondEvent.pageX, firstEvent.pageY - secondEvent.pageY);
251
+ }
252
+
253
+ /**
254
+ * Get the ratio of the point in the horizontal center of the area.
255
+ */
256
+ function getHorizontalCenterRatio(point, area) {
257
+ const {
258
+ left,
259
+ width
260
+ } = area;
261
+ return (point.x - left) / width;
262
+ }
263
+ function preventDefault(event) {
264
+ event.preventDefault();
265
+ }
266
+ function getVerticalCenterRatio(point, area) {
267
+ const {
268
+ top,
269
+ height
270
+ } = area;
271
+ return (point.y - top) / height * -1 + 1;
272
+ }
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ import { ZoomContext } from './ZoomContext';
3
+ /**
4
+ * Get access to the zoom state.
5
+ *
6
+ * @returns {ZoomState} The zoom state.
7
+ */
8
+ export function useZoom() {
9
+ const {
10
+ data,
11
+ isInitialized
12
+ } = React.useContext(ZoomContext);
13
+ if (!isInitialized) {
14
+ throw new Error(['MUI X: Could not find the zoom context.', 'It looks like you rendered your component outside of a ChartsContainer parent component.'].join('\n'));
15
+ }
16
+ return data;
17
+ }
@@ -0,0 +1,5 @@
1
+ // # Zoom & Pan
2
+
3
+ export * from './ZoomProvider/useZoom';
4
+ export * from './ZoomProvider/ZoomSetup';
5
+ export {};
@@ -0,0 +1 @@
1
+ export { useHeatmapSeries as unstable_useHeatmapSeries } from './useSeries';
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ import { useSeries } from '@mui/x-charts/internals';
3
+
4
+ /**
5
+ * Get access to the internal state of heatmap series.
6
+ * The returned object contains:
7
+ * - series: a mapping from ids to series attributes.
8
+ * - seriesOrder: the array of series ids.
9
+ * @returns { series: Record<SeriesId, DefaultizedHeatmapSeriesType>; seriesOrder: SeriesId[]; } | undefined heatmapSeries
10
+ */
11
+ export function useHeatmapSeries() {
12
+ const series = useSeries();
13
+ return React.useMemo(() => series.heatmap, [series.heatmap]);
14
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @mui/x-charts-pro v7.0.0-alpha.0
3
+ *
4
+ * @license MUI X Commercial
5
+ * This source code is licensed under the commercial license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import './typeOverloads/modules';
9
+
10
+ // exports from MIT package
11
+ export * from '@mui/x-charts/constants';
12
+ export * from '@mui/x-charts/context';
13
+ export * from '@mui/x-charts/hooks';
14
+ export * from '@mui/x-charts/colorPalettes';
15
+ export * from '@mui/x-charts/models';
16
+ export * from '@mui/x-charts/ChartsClipPath';
17
+ export * from '@mui/x-charts/ChartsReferenceLine';
18
+ export * from '@mui/x-charts/ChartsAxis';
19
+ export * from '@mui/x-charts/ChartsXAxis';
20
+ export * from '@mui/x-charts/ChartsYAxis';
21
+ export * from '@mui/x-charts/ChartsGrid';
22
+ export * from '@mui/x-charts/ChartsText';
23
+ export * from '@mui/x-charts/ChartsTooltip';
24
+ export * from '@mui/x-charts/ChartsLegend';
25
+ export * from '@mui/x-charts/ChartsAxisHighlight';
26
+ export * from '@mui/x-charts/ChartsVoronoiHandler';
27
+ export * from '@mui/x-charts/ChartsOnAxisClickHandler';
28
+ export * from '@mui/x-charts/BarChart';
29
+ export * from '@mui/x-charts/LineChart';
30
+ export * from '@mui/x-charts/PieChart';
31
+ export * from '@mui/x-charts/ScatterChart';
32
+ export * from '@mui/x-charts/SparkLineChart';
33
+ export * from '@mui/x-charts/Gauge';
34
+ export * from '@mui/x-charts/ChartsSurface';
35
+
36
+ // Pro components
37
+ export * from './Heatmap';
38
+ export * from './ResponsiveChartContainerPro';
39
+ export * from './ChartContainerPro';
40
+ export * from './ScatterChartPro';
41
+ export * from './BarChartPro';
42
+ export * from './LineChartPro';
43
+
44
+ // Pro context
45
+ export * from './context';
@@ -0,0 +1,13 @@
1
+ import { ponyfillGlobal } from '@mui/utils';
2
+ export const getReleaseInfo = () => {
3
+ const releaseInfo = "MTcyMzE1NDQwMDAwMA==";
4
+ if (process.env.NODE_ENV !== 'production') {
5
+ // A simple hack to set the value in the test environment (has no build step).
6
+ // eslint-disable-next-line no-useless-concat
7
+ if (releaseInfo === '__RELEASE' + '_INFO__') {
8
+ // eslint-disable-next-line no-underscore-dangle
9
+ return ponyfillGlobal.__MUI_RELEASE_INFO__;
10
+ }
11
+ }
12
+ return releaseInfo;
13
+ };
@@ -0,0 +1 @@
1
+ export * from './seriesType';