@mui/x-charts-pro 9.4.0 → 9.5.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 (74) hide show
  1. package/BarChartPro/BarChartPro.js +1 -1
  2. package/BarChartPro/BarChartPro.mjs +2 -2
  3. package/CHANGELOG.md +100 -0
  4. package/ChartsDataProviderPro/ChartsDataProviderPro.js +2 -2
  5. package/ChartsDataProviderPro/ChartsDataProviderPro.mjs +2 -2
  6. package/FunnelChart/funnel.types.d.mts +1 -1
  7. package/FunnelChart/funnel.types.d.ts +1 -1
  8. package/LineChartPro/LineChartPro.js +1 -1
  9. package/LineChartPro/LineChartPro.mjs +2 -2
  10. package/PieChartPro/PieChartPro.js +1 -1
  11. package/PieChartPro/PieChartPro.mjs +2 -2
  12. package/RadarChartPro/RadarChartPro.js +1 -1
  13. package/RadarChartPro/RadarChartPro.mjs +2 -2
  14. package/ScatterChartPro/ScatterChartPro.js +8 -4
  15. package/ScatterChartPro/ScatterChartPro.mjs +9 -5
  16. package/ScatterChartPro/ScatterChartPro.plugins.d.mts +2 -2
  17. package/ScatterChartPro/ScatterChartPro.plugins.d.ts +2 -2
  18. package/ScatterChartPro/ScatterChartPro.plugins.js +1 -1
  19. package/ScatterChartPro/ScatterChartPro.plugins.mjs +2 -2
  20. package/index.js +1 -1
  21. package/index.mjs +1 -1
  22. package/internals/plugins/allPlugins.d.mts +5 -5
  23. package/internals/plugins/allPlugins.d.ts +5 -5
  24. package/internals/plugins/allPlugins.js +2 -2
  25. package/internals/plugins/allPlugins.mjs +3 -3
  26. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.selectors.d.mts +36 -4
  27. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.selectors.d.ts +36 -4
  28. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.selectors.js +2 -4
  29. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.selectors.mjs +1 -3
  30. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.types.d.mts +11 -11
  31. package/internals/plugins/useChartProZoom/ZoomInteractionConfig.types.d.ts +11 -11
  32. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnDrag.d.mts +0 -1
  33. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnDrag.d.ts +0 -1
  34. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnDrag.js +9 -65
  35. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnDrag.mjs +9 -64
  36. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnPressAndDrag.d.mts +0 -1
  37. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnPressAndDrag.d.ts +0 -1
  38. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnPressAndDrag.js +9 -69
  39. package/internals/plugins/useChartProZoom/gestureHooks/usePanOnPressAndDrag.mjs +9 -68
  40. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnPinch.d.mts +0 -1
  41. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnPinch.d.ts +0 -1
  42. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnPinch.js +9 -39
  43. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnPinch.mjs +10 -39
  44. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnWheel.d.mts +0 -1
  45. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnWheel.d.ts +0 -1
  46. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnWheel.js +9 -58
  47. package/internals/plugins/useChartProZoom/gestureHooks/useZoomOnWheel.mjs +10 -58
  48. package/internals/plugins/zoomGestures/index.d.mts +5 -0
  49. package/internals/plugins/zoomGestures/index.d.ts +5 -0
  50. package/internals/plugins/zoomGestures/index.js +33 -0
  51. package/internals/plugins/zoomGestures/index.mjs +4 -0
  52. package/internals/plugins/zoomGestures/useDragGesture.d.mts +30 -0
  53. package/internals/plugins/zoomGestures/useDragGesture.d.ts +30 -0
  54. package/internals/plugins/zoomGestures/useDragGesture.js +105 -0
  55. package/internals/plugins/zoomGestures/useDragGesture.mjs +99 -0
  56. package/internals/plugins/zoomGestures/useDragOnPressGesture.d.mts +30 -0
  57. package/internals/plugins/zoomGestures/useDragOnPressGesture.d.ts +30 -0
  58. package/internals/plugins/zoomGestures/useDragOnPressGesture.js +105 -0
  59. package/internals/plugins/zoomGestures/useDragOnPressGesture.mjs +99 -0
  60. package/internals/plugins/zoomGestures/usePinchGesture.d.mts +22 -0
  61. package/internals/plugins/zoomGestures/usePinchGesture.d.ts +22 -0
  62. package/internals/plugins/zoomGestures/usePinchGesture.js +77 -0
  63. package/internals/plugins/zoomGestures/usePinchGesture.mjs +71 -0
  64. package/internals/plugins/zoomGestures/useWheelGesture.d.mts +21 -0
  65. package/internals/plugins/zoomGestures/useWheelGesture.d.ts +21 -0
  66. package/internals/plugins/zoomGestures/useWheelGesture.js +78 -0
  67. package/internals/plugins/zoomGestures/useWheelGesture.mjs +72 -0
  68. package/internals/plugins/zoomGestures/zoomGestures.types.d.mts +29 -0
  69. package/internals/plugins/zoomGestures/zoomGestures.types.d.ts +29 -0
  70. package/internals/plugins/zoomGestures/zoomGestures.types.js +5 -0
  71. package/internals/plugins/zoomGestures/zoomGestures.types.mjs +1 -0
  72. package/models/seriesType/heatmap.d.mts +1 -1
  73. package/models/seriesType/heatmap.d.ts +1 -1
  74. package/package.json +3 -3
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { rafThrottle } from '@mui/x-internals/rafThrottle';
5
+ /**
6
+ * Generic drag-to-pan gesture binding.
7
+ *
8
+ * It owns the listener lifecycle, and lets you create your own interactions by providing the delta change of the interaction.
9
+ */
10
+ export function useDragGesture(instance, options) {
11
+ const {
12
+ enabled,
13
+ config,
14
+ onPanStart,
15
+ onPan,
16
+ onPanEnd
17
+ } = options;
18
+ const {
19
+ chartsLayerContainerRef
20
+ } = instance;
21
+
22
+ // Keep the latest handlers in a ref so changing them doesn't rebind listeners.
23
+ const handlersRef = React.useRef({
24
+ onPanStart,
25
+ onPan,
26
+ onPanEnd
27
+ });
28
+ React.useEffect(() => {
29
+ handlersRef.current = {
30
+ onPanStart,
31
+ onPan,
32
+ onPanEnd
33
+ };
34
+ });
35
+ React.useEffect(() => {
36
+ if (!enabled) {
37
+ return;
38
+ }
39
+ instance.updateZoomInteractionListeners('zoomPan', {
40
+ requiredKeys: config?.requiredKeys,
41
+ pointerMode: config?.pointerMode,
42
+ pointerOptions: {
43
+ mouse: config?.mouse,
44
+ touch: config?.touch
45
+ }
46
+ });
47
+ }, [enabled, config, instance]);
48
+ React.useEffect(() => {
49
+ const element = chartsLayerContainerRef.current;
50
+ if (element === null || !enabled) {
51
+ return () => {};
52
+ }
53
+ let isInteracting = false;
54
+ let lastEvent = null;
55
+ const accumulated = {
56
+ x: 0,
57
+ y: 0
58
+ };
59
+ const handlePanStart = event => {
60
+ if (!event.detail.target?.closest('[data-charts-zoom-slider]')) {
61
+ isInteracting = true;
62
+ handlersRef.current.onPanStart?.(event);
63
+ }
64
+ };
65
+ const handlePanEnd = event => {
66
+ isInteracting = false;
67
+ handlersRef.current.onPanEnd?.(event);
68
+ };
69
+ const throttled = rafThrottle(() => {
70
+ const delta = {
71
+ x: accumulated.x,
72
+ y: accumulated.y
73
+ };
74
+ accumulated.x = 0;
75
+ accumulated.y = 0;
76
+ if (lastEvent) {
77
+ handlersRef.current.onPan(delta, lastEvent);
78
+ }
79
+ });
80
+ const handlePan = event => {
81
+ if (!isInteracting) {
82
+ return;
83
+ }
84
+ lastEvent = event;
85
+ accumulated.x += event.detail.deltaX;
86
+ accumulated.y += event.detail.deltaY;
87
+ throttled();
88
+ };
89
+ const panHandler = instance.addInteractionListener('zoomPan', handlePan);
90
+ const panStartHandler = instance.addInteractionListener('zoomPanStart', handlePanStart);
91
+ const panEndHandler = instance.addInteractionListener('zoomPanEnd', handlePanEnd);
92
+ return () => {
93
+ panHandler.cleanup();
94
+ panStartHandler.cleanup();
95
+ panEndHandler.cleanup();
96
+ throttled.clear();
97
+ };
98
+ }, [instance, chartsLayerContainerRef, enabled]);
99
+ }
@@ -0,0 +1,30 @@
1
+ import type { PanEvent } from '@mui/x-internal-gestures/core';
2
+ import type { ChartPoint, GestureInstance, PanGestureConfig } from "./zoomGestures.types.mjs";
3
+ export interface UseDragOnPressGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Pointer and keyboard gating for the gesture. */
7
+ config?: PanGestureConfig;
8
+ /**
9
+ * Called when the drag starts.
10
+ * @param {PanEvent} event The pan start event.
11
+ */
12
+ onPanStart?: (event: PanEvent) => void;
13
+ /**
14
+ * Called (rAF-throttled) on each drag update.
15
+ * @param {ChartPoint} delta The pixel delta since the last call.
16
+ * @param {PanEvent} event The pan event.
17
+ */
18
+ onPan: (delta: ChartPoint, event: PanEvent) => void;
19
+ /**
20
+ * Called when the drag ends.
21
+ * @param {PanEvent} event The pan end event.
22
+ */
23
+ onPanEnd?: (event: PanEvent) => void;
24
+ }
25
+ /**
26
+ * Generic press-and-drag-to-pan gesture binding.
27
+ *
28
+ * It owns the listener lifecycle, and lets you create your own interactions by providing the delta change of the interaction.
29
+ */
30
+ export declare function useDragOnPressGesture(instance: GestureInstance, options: UseDragOnPressGestureOptions): void;
@@ -0,0 +1,30 @@
1
+ import type { PanEvent } from '@mui/x-internal-gestures/core';
2
+ import type { ChartPoint, GestureInstance, PanGestureConfig } from "./zoomGestures.types.js";
3
+ export interface UseDragOnPressGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Pointer and keyboard gating for the gesture. */
7
+ config?: PanGestureConfig;
8
+ /**
9
+ * Called when the drag starts.
10
+ * @param {PanEvent} event The pan start event.
11
+ */
12
+ onPanStart?: (event: PanEvent) => void;
13
+ /**
14
+ * Called (rAF-throttled) on each drag update.
15
+ * @param {ChartPoint} delta The pixel delta since the last call.
16
+ * @param {PanEvent} event The pan event.
17
+ */
18
+ onPan: (delta: ChartPoint, event: PanEvent) => void;
19
+ /**
20
+ * Called when the drag ends.
21
+ * @param {PanEvent} event The pan end event.
22
+ */
23
+ onPanEnd?: (event: PanEvent) => void;
24
+ }
25
+ /**
26
+ * Generic press-and-drag-to-pan gesture binding.
27
+ *
28
+ * It owns the listener lifecycle, and lets you create your own interactions by providing the delta change of the interaction.
29
+ */
30
+ export declare function useDragOnPressGesture(instance: GestureInstance, options: UseDragOnPressGestureOptions): void;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useDragOnPressGesture = useDragOnPressGesture;
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _rafThrottle = require("@mui/x-internals/rafThrottle");
11
+ /**
12
+ * Generic press-and-drag-to-pan gesture binding.
13
+ *
14
+ * It owns the listener lifecycle, and lets you create your own interactions by providing the delta change of the interaction.
15
+ */
16
+ function useDragOnPressGesture(instance, options) {
17
+ const {
18
+ enabled,
19
+ config,
20
+ onPanStart,
21
+ onPan,
22
+ onPanEnd
23
+ } = options;
24
+ const {
25
+ chartsLayerContainerRef
26
+ } = instance;
27
+
28
+ // Keep the latest handlers in a ref so changing them doesn't rebind listeners.
29
+ const handlersRef = React.useRef({
30
+ onPanStart,
31
+ onPan,
32
+ onPanEnd
33
+ });
34
+ React.useEffect(() => {
35
+ handlersRef.current = {
36
+ onPanStart,
37
+ onPan,
38
+ onPanEnd
39
+ };
40
+ });
41
+ React.useEffect(() => {
42
+ if (!enabled) {
43
+ return;
44
+ }
45
+ instance.updateZoomInteractionListeners('zoomPressAndDrag', {
46
+ requiredKeys: config?.requiredKeys,
47
+ pointerMode: config?.pointerMode,
48
+ pointerOptions: {
49
+ mouse: config?.mouse,
50
+ touch: config?.touch
51
+ }
52
+ });
53
+ }, [enabled, config, instance]);
54
+ React.useEffect(() => {
55
+ const element = chartsLayerContainerRef.current;
56
+ if (element === null || !enabled) {
57
+ return () => {};
58
+ }
59
+ let isInteracting = false;
60
+ let lastEvent = null;
61
+ const accumulated = {
62
+ x: 0,
63
+ y: 0
64
+ };
65
+ const handlePanStart = event => {
66
+ if (!event.detail.target?.closest('[data-charts-zoom-slider]')) {
67
+ isInteracting = true;
68
+ handlersRef.current.onPanStart?.(event);
69
+ }
70
+ };
71
+ const handlePanEnd = event => {
72
+ isInteracting = false;
73
+ handlersRef.current.onPanEnd?.(event);
74
+ };
75
+ const throttled = (0, _rafThrottle.rafThrottle)(() => {
76
+ const delta = {
77
+ x: accumulated.x,
78
+ y: accumulated.y
79
+ };
80
+ accumulated.x = 0;
81
+ accumulated.y = 0;
82
+ if (lastEvent) {
83
+ handlersRef.current.onPan(delta, lastEvent);
84
+ }
85
+ });
86
+ const handlePan = event => {
87
+ if (!isInteracting) {
88
+ return;
89
+ }
90
+ lastEvent = event;
91
+ accumulated.x += event.detail.deltaX;
92
+ accumulated.y += event.detail.deltaY;
93
+ throttled();
94
+ };
95
+ const panHandler = instance.addInteractionListener('zoomPressAndDrag', handlePan);
96
+ const panStartHandler = instance.addInteractionListener('zoomPressAndDragStart', handlePanStart);
97
+ const panEndHandler = instance.addInteractionListener('zoomPressAndDragEnd', handlePanEnd);
98
+ return () => {
99
+ panHandler.cleanup();
100
+ panStartHandler.cleanup();
101
+ panEndHandler.cleanup();
102
+ throttled.clear();
103
+ };
104
+ }, [instance, chartsLayerContainerRef, enabled]);
105
+ }
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { rafThrottle } from '@mui/x-internals/rafThrottle';
5
+ /**
6
+ * Generic press-and-drag-to-pan gesture binding.
7
+ *
8
+ * It owns the listener lifecycle, and lets you create your own interactions by providing the delta change of the interaction.
9
+ */
10
+ export function useDragOnPressGesture(instance, options) {
11
+ const {
12
+ enabled,
13
+ config,
14
+ onPanStart,
15
+ onPan,
16
+ onPanEnd
17
+ } = options;
18
+ const {
19
+ chartsLayerContainerRef
20
+ } = instance;
21
+
22
+ // Keep the latest handlers in a ref so changing them doesn't rebind listeners.
23
+ const handlersRef = React.useRef({
24
+ onPanStart,
25
+ onPan,
26
+ onPanEnd
27
+ });
28
+ React.useEffect(() => {
29
+ handlersRef.current = {
30
+ onPanStart,
31
+ onPan,
32
+ onPanEnd
33
+ };
34
+ });
35
+ React.useEffect(() => {
36
+ if (!enabled) {
37
+ return;
38
+ }
39
+ instance.updateZoomInteractionListeners('zoomPressAndDrag', {
40
+ requiredKeys: config?.requiredKeys,
41
+ pointerMode: config?.pointerMode,
42
+ pointerOptions: {
43
+ mouse: config?.mouse,
44
+ touch: config?.touch
45
+ }
46
+ });
47
+ }, [enabled, config, instance]);
48
+ React.useEffect(() => {
49
+ const element = chartsLayerContainerRef.current;
50
+ if (element === null || !enabled) {
51
+ return () => {};
52
+ }
53
+ let isInteracting = false;
54
+ let lastEvent = null;
55
+ const accumulated = {
56
+ x: 0,
57
+ y: 0
58
+ };
59
+ const handlePanStart = event => {
60
+ if (!event.detail.target?.closest('[data-charts-zoom-slider]')) {
61
+ isInteracting = true;
62
+ handlersRef.current.onPanStart?.(event);
63
+ }
64
+ };
65
+ const handlePanEnd = event => {
66
+ isInteracting = false;
67
+ handlersRef.current.onPanEnd?.(event);
68
+ };
69
+ const throttled = rafThrottle(() => {
70
+ const delta = {
71
+ x: accumulated.x,
72
+ y: accumulated.y
73
+ };
74
+ accumulated.x = 0;
75
+ accumulated.y = 0;
76
+ if (lastEvent) {
77
+ handlersRef.current.onPan(delta, lastEvent);
78
+ }
79
+ });
80
+ const handlePan = event => {
81
+ if (!isInteracting) {
82
+ return;
83
+ }
84
+ lastEvent = event;
85
+ accumulated.x += event.detail.deltaX;
86
+ accumulated.y += event.detail.deltaY;
87
+ throttled();
88
+ };
89
+ const panHandler = instance.addInteractionListener('zoomPressAndDrag', handlePan);
90
+ const panStartHandler = instance.addInteractionListener('zoomPressAndDragStart', handlePanStart);
91
+ const panEndHandler = instance.addInteractionListener('zoomPressAndDragEnd', handlePanEnd);
92
+ return () => {
93
+ panHandler.cleanup();
94
+ panStartHandler.cleanup();
95
+ panEndHandler.cleanup();
96
+ throttled.clear();
97
+ };
98
+ }, [instance, chartsLayerContainerRef, enabled]);
99
+ }
@@ -0,0 +1,22 @@
1
+ import type { KeyboardKey } from '@mui/x-internal-gestures/core';
2
+ import type { ChartPoint, GestureInstance } from "./zoomGestures.types.mjs";
3
+ export interface UsePinchGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Keys that must be held for the pinch to trigger the gesture. */
7
+ requiredKeys?: KeyboardKey[];
8
+ /**
9
+ * Called (rAF-throttled) on each pinch update.
10
+ *
11
+ * @param {ChartPoint} point The pinch centroid, in SVG coordinates.
12
+ * @param {number} deltaScale The scale change since the last call.
13
+ * @param {number} direction `> 0` when zooming in, `< 0` when zooming out.
14
+ */
15
+ onPinch: (point: ChartPoint, deltaScale: number, direction: number) => void;
16
+ }
17
+ /**
18
+ * Generic pinch gesture binding.
19
+ *
20
+ * It owns the listener lifecycle, and lets you create your own interactions from the centroid and scale delta it forwards to `onPinch`.
21
+ */
22
+ export declare function usePinchGesture(instance: GestureInstance, options: UsePinchGestureOptions): void;
@@ -0,0 +1,22 @@
1
+ import type { KeyboardKey } from '@mui/x-internal-gestures/core';
2
+ import type { ChartPoint, GestureInstance } from "./zoomGestures.types.js";
3
+ export interface UsePinchGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Keys that must be held for the pinch to trigger the gesture. */
7
+ requiredKeys?: KeyboardKey[];
8
+ /**
9
+ * Called (rAF-throttled) on each pinch update.
10
+ *
11
+ * @param {ChartPoint} point The pinch centroid, in SVG coordinates.
12
+ * @param {number} deltaScale The scale change since the last call.
13
+ * @param {number} direction `> 0` when zooming in, `< 0` when zooming out.
14
+ */
15
+ onPinch: (point: ChartPoint, deltaScale: number, direction: number) => void;
16
+ }
17
+ /**
18
+ * Generic pinch gesture binding.
19
+ *
20
+ * It owns the listener lifecycle, and lets you create your own interactions from the centroid and scale delta it forwards to `onPinch`.
21
+ */
22
+ export declare function usePinchGesture(instance: GestureInstance, options: UsePinchGestureOptions): void;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.usePinchGesture = usePinchGesture;
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _internals = require("@mui/x-charts/internals");
11
+ var _rafThrottle = require("@mui/x-internals/rafThrottle");
12
+ /**
13
+ * Generic pinch gesture binding.
14
+ *
15
+ * It owns the listener lifecycle, and lets you create your own interactions from the centroid and scale delta it forwards to `onPinch`.
16
+ */
17
+ function usePinchGesture(instance, options) {
18
+ const {
19
+ enabled,
20
+ requiredKeys,
21
+ onPinch
22
+ } = options;
23
+ const {
24
+ chartsLayerContainerRef
25
+ } = instance;
26
+ const onPinchRef = React.useRef(onPinch);
27
+ React.useEffect(() => {
28
+ onPinchRef.current = onPinch;
29
+ });
30
+ React.useEffect(() => {
31
+ if (!enabled) {
32
+ return;
33
+ }
34
+ instance.updateZoomInteractionListeners('zoomPinch', {
35
+ requiredKeys
36
+ });
37
+ }, [enabled, requiredKeys, instance]);
38
+ React.useEffect(() => {
39
+ const element = chartsLayerContainerRef.current;
40
+ if (element === null || !enabled) {
41
+ return () => {};
42
+ }
43
+ const latest = {
44
+ point: {
45
+ x: 0,
46
+ y: 0
47
+ },
48
+ deltaScale: 0,
49
+ direction: 0,
50
+ valid: false
51
+ };
52
+ const flush = (0, _rafThrottle.rafThrottle)(() => {
53
+ if (latest.valid) {
54
+ onPinchRef.current(latest.point, latest.deltaScale, latest.direction);
55
+ latest.valid = false;
56
+ }
57
+ });
58
+ const handler = instance.addInteractionListener('zoomPinch', event => {
59
+ // A direction of 0 means the pinch gesture is not yet meaningful.
60
+ if (event.detail.direction === 0) {
61
+ return;
62
+ }
63
+ latest.point = (0, _internals.getChartPoint)(element, {
64
+ clientX: event.detail.centroid.x,
65
+ clientY: event.detail.centroid.y
66
+ });
67
+ latest.deltaScale = event.detail.deltaScale;
68
+ latest.direction = event.detail.direction;
69
+ latest.valid = true;
70
+ flush();
71
+ });
72
+ return () => {
73
+ handler.cleanup();
74
+ flush.clear();
75
+ };
76
+ }, [chartsLayerContainerRef, enabled, instance]);
77
+ }
@@ -0,0 +1,71 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { getChartPoint } from '@mui/x-charts/internals';
5
+ import { rafThrottle } from '@mui/x-internals/rafThrottle';
6
+ /**
7
+ * Generic pinch gesture binding.
8
+ *
9
+ * It owns the listener lifecycle, and lets you create your own interactions from the centroid and scale delta it forwards to `onPinch`.
10
+ */
11
+ export function usePinchGesture(instance, options) {
12
+ const {
13
+ enabled,
14
+ requiredKeys,
15
+ onPinch
16
+ } = options;
17
+ const {
18
+ chartsLayerContainerRef
19
+ } = instance;
20
+ const onPinchRef = React.useRef(onPinch);
21
+ React.useEffect(() => {
22
+ onPinchRef.current = onPinch;
23
+ });
24
+ React.useEffect(() => {
25
+ if (!enabled) {
26
+ return;
27
+ }
28
+ instance.updateZoomInteractionListeners('zoomPinch', {
29
+ requiredKeys
30
+ });
31
+ }, [enabled, requiredKeys, instance]);
32
+ React.useEffect(() => {
33
+ const element = chartsLayerContainerRef.current;
34
+ if (element === null || !enabled) {
35
+ return () => {};
36
+ }
37
+ const latest = {
38
+ point: {
39
+ x: 0,
40
+ y: 0
41
+ },
42
+ deltaScale: 0,
43
+ direction: 0,
44
+ valid: false
45
+ };
46
+ const flush = rafThrottle(() => {
47
+ if (latest.valid) {
48
+ onPinchRef.current(latest.point, latest.deltaScale, latest.direction);
49
+ latest.valid = false;
50
+ }
51
+ });
52
+ const handler = instance.addInteractionListener('zoomPinch', event => {
53
+ // A direction of 0 means the pinch gesture is not yet meaningful.
54
+ if (event.detail.direction === 0) {
55
+ return;
56
+ }
57
+ latest.point = getChartPoint(element, {
58
+ clientX: event.detail.centroid.x,
59
+ clientY: event.detail.centroid.y
60
+ });
61
+ latest.deltaScale = event.detail.deltaScale;
62
+ latest.direction = event.detail.direction;
63
+ latest.valid = true;
64
+ flush();
65
+ });
66
+ return () => {
67
+ handler.cleanup();
68
+ flush.clear();
69
+ };
70
+ }, [chartsLayerContainerRef, enabled, instance]);
71
+ }
@@ -0,0 +1,21 @@
1
+ import { type KeyboardKey } from '@mui/x-internal-gestures/core';
2
+ import { type ChartPoint, type GestureInstance } from "./zoomGestures.types.mjs";
3
+ export interface UseWheelGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Keys that must be held for the wheel to trigger the gesture. */
7
+ requiredKeys?: KeyboardKey[];
8
+ /**
9
+ * Called on each wheel tick inside the drawing area.
10
+ *
11
+ * @param {ChartPoint} point The wheel focal point, in SVG coordinates.
12
+ * @param {WheelEvent} event The `WheelEvent`.
13
+ */
14
+ onWheel: (point: ChartPoint, event: WheelEvent) => void;
15
+ }
16
+ /**
17
+ * Generic wheel gesture binding.
18
+ *
19
+ * It owns the listener lifecycle, and lets you create your own interactions from the focal point and wheel event it forwards to `onWheel`.
20
+ */
21
+ export declare function useWheelGesture(instance: GestureInstance, options: UseWheelGestureOptions): void;
@@ -0,0 +1,21 @@
1
+ import { type KeyboardKey } from '@mui/x-internal-gestures/core';
2
+ import { type ChartPoint, type GestureInstance } from "./zoomGestures.types.js";
3
+ export interface UseWheelGestureOptions {
4
+ /** Whether the gesture is active. */
5
+ enabled: boolean;
6
+ /** Keys that must be held for the wheel to trigger the gesture. */
7
+ requiredKeys?: KeyboardKey[];
8
+ /**
9
+ * Called on each wheel tick inside the drawing area.
10
+ *
11
+ * @param {ChartPoint} point The wheel focal point, in SVG coordinates.
12
+ * @param {WheelEvent} event The `WheelEvent`.
13
+ */
14
+ onWheel: (point: ChartPoint, event: WheelEvent) => void;
15
+ }
16
+ /**
17
+ * Generic wheel gesture binding.
18
+ *
19
+ * It owns the listener lifecycle, and lets you create your own interactions from the focal point and wheel event it forwards to `onWheel`.
20
+ */
21
+ export declare function useWheelGesture(instance: GestureInstance, options: UseWheelGestureOptions): void;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.useWheelGesture = useWheelGesture;
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _rafThrottle = require("@mui/x-internals/rafThrottle");
11
+ var _internals = require("@mui/x-charts/internals");
12
+ /**
13
+ * Generic wheel gesture binding.
14
+ *
15
+ * It owns the listener lifecycle, and lets you create your own interactions from the focal point and wheel event it forwards to `onWheel`.
16
+ */
17
+ function useWheelGesture(instance, options) {
18
+ const {
19
+ enabled,
20
+ requiredKeys,
21
+ onWheel
22
+ } = options;
23
+ const {
24
+ chartsLayerContainerRef
25
+ } = instance;
26
+ const startedOutsideRef = React.useRef(false);
27
+ const startedOutsideTimeoutRef = React.useRef(null);
28
+ const onWheelRef = React.useRef(onWheel);
29
+ React.useEffect(() => {
30
+ onWheelRef.current = onWheel;
31
+ });
32
+ React.useEffect(() => {
33
+ if (!enabled) {
34
+ return;
35
+ }
36
+ instance.updateZoomInteractionListeners('zoomTurnWheel', {
37
+ requiredKeys
38
+ });
39
+ }, [enabled, requiredKeys, instance]);
40
+ React.useEffect(() => {
41
+ const element = chartsLayerContainerRef.current;
42
+ if (element === null || !enabled) {
43
+ return () => {};
44
+ }
45
+ const rafThrottledOnWheel = (0, _rafThrottle.rafThrottle)(onWheelRef.current);
46
+ const handler = instance.addInteractionListener('zoomTurnWheel', event => {
47
+ const point = (0, _internals.getChartPoint)(element, {
48
+ clientX: event.detail.centroid.x,
49
+ clientY: event.detail.centroid.y
50
+ });
51
+
52
+ // Ignore wheel events that started outside the chart area (e.g. while page-scrolling
53
+ // over the chart). The timeout debounces re-entry caused by the scroll itself.
54
+ if (startedOutsideRef.current || !instance.isPointInside(point.x, point.y)) {
55
+ startedOutsideRef.current = true;
56
+ if (startedOutsideTimeoutRef.current) {
57
+ clearTimeout(startedOutsideTimeoutRef.current);
58
+ }
59
+ startedOutsideTimeoutRef.current = setTimeout(() => {
60
+ startedOutsideRef.current = false;
61
+ startedOutsideTimeoutRef.current = null;
62
+ }, 100);
63
+ return;
64
+ }
65
+ event.detail.srcEvent.preventDefault();
66
+ rafThrottledOnWheel(point, event.detail.srcEvent);
67
+ });
68
+ return () => {
69
+ handler.cleanup();
70
+ if (startedOutsideTimeoutRef.current) {
71
+ clearTimeout(startedOutsideTimeoutRef.current);
72
+ startedOutsideTimeoutRef.current = null;
73
+ }
74
+ startedOutsideRef.current = false;
75
+ rafThrottledOnWheel.clear();
76
+ };
77
+ }, [chartsLayerContainerRef, enabled, instance]);
78
+ }