@mui/x-charts-pro 8.1.0 → 8.3.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 (198) hide show
  1. package/BarChartPro/BarChartPro.d.ts +7 -1
  2. package/BarChartPro/BarChartPro.js +62 -5
  3. package/CHANGELOG.md +233 -7
  4. package/ChartContainerPro/useChartContainerProProps.d.ts +1 -1
  5. package/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  6. package/ChartDataProviderPro/useChartDataProviderProProps.d.ts +2 -2
  7. package/ChartZoomSlider/ChartZoomSlider.d.ts +5 -0
  8. package/ChartZoomSlider/ChartZoomSlider.js +47 -0
  9. package/ChartZoomSlider/index.d.ts +2 -0
  10. package/ChartZoomSlider/index.js +27 -0
  11. package/ChartZoomSlider/internals/ChartAxisZoomSlider.d.ts +23 -0
  12. package/ChartZoomSlider/internals/ChartAxisZoomSlider.js +348 -0
  13. package/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.d.ts +12 -0
  14. package/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.js +92 -0
  15. package/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.d.ts +17 -0
  16. package/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.js +27 -0
  17. package/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -0
  18. package/ChartsToolbarPro/ChartsToolbarPro.js +31 -0
  19. package/ChartsToolbarPro/index.d.ts +1 -0
  20. package/ChartsToolbarPro/index.js +16 -0
  21. package/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.d.ts +13 -0
  22. package/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.js +36 -0
  23. package/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.d.ts +13 -0
  24. package/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.js +36 -0
  25. package/FunnelChart/FunnelChart.js +9 -8
  26. package/FunnelChart/FunnelPlot.d.ts +5 -0
  27. package/FunnelChart/FunnelPlot.js +36 -18
  28. package/FunnelChart/FunnelSection.d.ts +1 -0
  29. package/FunnelChart/FunnelSection.js +12 -7
  30. package/FunnelChart/curves/borderRadiusPolygon.d.ts +8 -0
  31. package/FunnelChart/curves/borderRadiusPolygon.js +42 -0
  32. package/FunnelChart/curves/bump.d.ts +27 -0
  33. package/FunnelChart/curves/bump.js +81 -0
  34. package/FunnelChart/curves/curve.types.d.ts +38 -0
  35. package/FunnelChart/curves/curve.types.js +5 -0
  36. package/FunnelChart/curves/getFunnelCurve.d.ts +3 -0
  37. package/FunnelChart/curves/getFunnelCurve.js +30 -0
  38. package/FunnelChart/curves/index.d.ts +2 -0
  39. package/FunnelChart/curves/index.js +27 -0
  40. package/FunnelChart/curves/linear.d.ts +32 -0
  41. package/FunnelChart/curves/linear.js +88 -0
  42. package/FunnelChart/curves/pyramid.d.ts +34 -0
  43. package/FunnelChart/curves/pyramid.js +127 -0
  44. package/FunnelChart/curves/step-pyramid.d.ts +31 -0
  45. package/FunnelChart/curves/step-pyramid.js +107 -0
  46. package/FunnelChart/curves/step.d.ts +32 -0
  47. package/FunnelChart/curves/step.js +88 -0
  48. package/FunnelChart/curves/utils.d.ts +4 -0
  49. package/FunnelChart/curves/utils.js +29 -0
  50. package/FunnelChart/funnel.types.d.ts +25 -4
  51. package/FunnelChart/funnelPlotSlots.types.d.ts +1 -1
  52. package/FunnelChart/funnelSectionClasses.d.ts +6 -2
  53. package/FunnelChart/funnelSectionClasses.js +5 -2
  54. package/FunnelChart/index.d.ts +3 -2
  55. package/FunnelChart/seriesConfig/getSeriesWithDefaultValues.js +1 -0
  56. package/FunnelChart/useFunnelChartProps.d.ts +1 -6
  57. package/FunnelChart/useFunnelChartProps.js +7 -15
  58. package/Heatmap/Heatmap.d.ts +3 -3
  59. package/Heatmap/Heatmap.js +3 -21
  60. package/LineChartPro/LineChartPro.d.ts +7 -1
  61. package/LineChartPro/LineChartPro.js +62 -5
  62. package/ScatterChartPro/ScatterChartPro.d.ts +7 -1
  63. package/ScatterChartPro/ScatterChartPro.js +62 -5
  64. package/esm/BarChartPro/BarChartPro.d.ts +7 -1
  65. package/esm/BarChartPro/BarChartPro.js +62 -5
  66. package/esm/ChartContainerPro/useChartContainerProProps.d.ts +1 -1
  67. package/esm/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  68. package/esm/ChartDataProviderPro/useChartDataProviderProProps.d.ts +2 -2
  69. package/esm/ChartZoomSlider/ChartZoomSlider.d.ts +5 -0
  70. package/esm/ChartZoomSlider/ChartZoomSlider.js +41 -0
  71. package/esm/ChartZoomSlider/index.d.ts +2 -0
  72. package/esm/ChartZoomSlider/index.js +2 -0
  73. package/esm/ChartZoomSlider/internals/ChartAxisZoomSlider.d.ts +23 -0
  74. package/esm/ChartZoomSlider/internals/ChartAxisZoomSlider.js +339 -0
  75. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.d.ts +12 -0
  76. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.js +85 -0
  77. package/esm/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.d.ts +17 -0
  78. package/esm/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.js +17 -0
  79. package/esm/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -0
  80. package/esm/ChartsToolbarPro/ChartsToolbarPro.js +24 -0
  81. package/esm/ChartsToolbarPro/index.d.ts +1 -0
  82. package/esm/ChartsToolbarPro/index.js +1 -0
  83. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.d.ts +13 -0
  84. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.js +29 -0
  85. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.d.ts +13 -0
  86. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.js +29 -0
  87. package/esm/FunnelChart/FunnelChart.js +9 -8
  88. package/esm/FunnelChart/FunnelPlot.d.ts +5 -0
  89. package/esm/FunnelChart/FunnelPlot.js +37 -19
  90. package/esm/FunnelChart/FunnelSection.d.ts +1 -0
  91. package/esm/FunnelChart/FunnelSection.js +12 -7
  92. package/esm/FunnelChart/curves/borderRadiusPolygon.d.ts +8 -0
  93. package/esm/FunnelChart/curves/borderRadiusPolygon.js +36 -0
  94. package/esm/FunnelChart/curves/bump.d.ts +27 -0
  95. package/esm/FunnelChart/curves/bump.js +74 -0
  96. package/esm/FunnelChart/curves/curve.types.d.ts +38 -0
  97. package/esm/FunnelChart/curves/curve.types.js +1 -0
  98. package/esm/FunnelChart/curves/getFunnelCurve.d.ts +3 -0
  99. package/esm/FunnelChart/curves/getFunnelCurve.js +23 -0
  100. package/esm/FunnelChart/curves/index.d.ts +2 -0
  101. package/esm/FunnelChart/curves/index.js +2 -0
  102. package/esm/FunnelChart/curves/linear.d.ts +32 -0
  103. package/esm/FunnelChart/curves/linear.js +82 -0
  104. package/esm/FunnelChart/curves/pyramid.d.ts +34 -0
  105. package/esm/FunnelChart/curves/pyramid.js +121 -0
  106. package/esm/FunnelChart/curves/step-pyramid.d.ts +31 -0
  107. package/esm/FunnelChart/curves/step-pyramid.js +101 -0
  108. package/esm/FunnelChart/curves/step.d.ts +32 -0
  109. package/esm/FunnelChart/curves/step.js +82 -0
  110. package/esm/FunnelChart/curves/utils.d.ts +4 -0
  111. package/esm/FunnelChart/curves/utils.js +19 -0
  112. package/esm/FunnelChart/funnel.types.d.ts +25 -4
  113. package/esm/FunnelChart/funnelPlotSlots.types.d.ts +1 -1
  114. package/esm/FunnelChart/funnelSectionClasses.d.ts +6 -2
  115. package/esm/FunnelChart/funnelSectionClasses.js +5 -2
  116. package/esm/FunnelChart/index.d.ts +3 -2
  117. package/esm/FunnelChart/seriesConfig/getSeriesWithDefaultValues.js +1 -0
  118. package/esm/FunnelChart/useFunnelChartProps.d.ts +1 -6
  119. package/esm/FunnelChart/useFunnelChartProps.js +7 -15
  120. package/esm/Heatmap/Heatmap.d.ts +3 -3
  121. package/esm/Heatmap/Heatmap.js +3 -21
  122. package/esm/LineChartPro/LineChartPro.d.ts +7 -1
  123. package/esm/LineChartPro/LineChartPro.js +62 -5
  124. package/esm/ScatterChartPro/ScatterChartPro.d.ts +7 -1
  125. package/esm/ScatterChartPro/ScatterChartPro.js +62 -5
  126. package/esm/index.d.ts +4 -1
  127. package/esm/index.js +5 -2
  128. package/esm/internals/material/icons.d.ts +3 -0
  129. package/esm/internals/material/icons.js +13 -0
  130. package/esm/internals/material/index.d.ts +4 -0
  131. package/esm/internals/material/index.js +12 -0
  132. package/esm/internals/plugins/useChartProExport/common.d.ts +1 -0
  133. package/esm/internals/plugins/useChartProExport/common.js +8 -0
  134. package/esm/internals/plugins/useChartProExport/exportImage.d.ts +3 -0
  135. package/esm/internals/plugins/useChartProExport/exportImage.js +85 -0
  136. package/esm/internals/plugins/useChartProExport/print.js +6 -50
  137. package/esm/internals/plugins/useChartProExport/useChartProExport.js +22 -2
  138. package/esm/internals/plugins/useChartProExport/useChartProExport.types.d.ts +32 -0
  139. package/esm/internals/plugins/useChartProZoom/calculateZoom.d.ts +23 -0
  140. package/esm/internals/plugins/useChartProZoom/calculateZoom.js +32 -0
  141. package/esm/internals/plugins/useChartProZoom/useChartProZoom.d.ts +1 -1
  142. package/esm/internals/plugins/useChartProZoom/useChartProZoom.js +46 -4
  143. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +84 -32
  144. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +3 -2
  145. package/esm/internals/plugins/useChartProZoom/useChartProZoom.types.d.ts +17 -2
  146. package/esm/internals/slots/chartBaseSlotProps.d.ts +10 -0
  147. package/esm/internals/slots/chartBaseSlotProps.js +1 -0
  148. package/esm/internals/slots/chartsBaseSlots.d.ts +6 -0
  149. package/esm/internals/slots/chartsBaseSlots.js +1 -0
  150. package/esm/internals/slots/chartsIconSlots.d.ts +14 -0
  151. package/esm/internals/slots/chartsIconSlots.js +1 -0
  152. package/esm/themeAugmentation/components.d.ts +0 -4
  153. package/esm/themeAugmentation/components.js +1 -0
  154. package/esm/themeAugmentation/index.d.ts +3 -3
  155. package/esm/themeAugmentation/overrides.d.ts +0 -3
  156. package/esm/themeAugmentation/overrides.js +2 -0
  157. package/esm/themeAugmentation/props.d.ts +0 -6
  158. package/esm/themeAugmentation/props.js +2 -0
  159. package/esm/typeOverloads/modules.d.ts +1 -1
  160. package/index.d.ts +4 -1
  161. package/index.js +90 -1
  162. package/internals/material/icons.d.ts +3 -0
  163. package/internals/material/icons.js +20 -0
  164. package/internals/material/index.d.ts +4 -0
  165. package/internals/material/index.js +19 -0
  166. package/internals/plugins/useChartProExport/common.d.ts +1 -0
  167. package/internals/plugins/useChartProExport/common.js +14 -0
  168. package/internals/plugins/useChartProExport/exportImage.d.ts +3 -0
  169. package/internals/plugins/useChartProExport/exportImage.js +95 -0
  170. package/internals/plugins/useChartProExport/print.js +6 -50
  171. package/internals/plugins/useChartProExport/useChartProExport.js +22 -2
  172. package/internals/plugins/useChartProExport/useChartProExport.types.d.ts +32 -0
  173. package/internals/plugins/useChartProZoom/calculateZoom.d.ts +23 -0
  174. package/internals/plugins/useChartProZoom/calculateZoom.js +39 -0
  175. package/internals/plugins/useChartProZoom/useChartProZoom.d.ts +1 -1
  176. package/internals/plugins/useChartProZoom/useChartProZoom.js +45 -3
  177. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +84 -32
  178. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +3 -2
  179. package/internals/plugins/useChartProZoom/useChartProZoom.types.d.ts +17 -2
  180. package/internals/slots/chartBaseSlotProps.d.ts +10 -0
  181. package/internals/slots/chartBaseSlotProps.js +5 -0
  182. package/internals/slots/chartsBaseSlots.d.ts +6 -0
  183. package/internals/slots/chartsBaseSlots.js +5 -0
  184. package/internals/slots/chartsIconSlots.d.ts +14 -0
  185. package/internals/slots/chartsIconSlots.js +5 -0
  186. package/package.json +10 -7
  187. package/themeAugmentation/components.d.ts +0 -4
  188. package/themeAugmentation/components.js +5 -0
  189. package/themeAugmentation/index.d.ts +3 -3
  190. package/themeAugmentation/overrides.d.ts +0 -3
  191. package/themeAugmentation/overrides.js +5 -0
  192. package/themeAugmentation/props.d.ts +0 -6
  193. package/themeAugmentation/props.js +5 -0
  194. package/typeOverloads/modules.d.ts +1 -1
  195. package/FunnelChart/funnelStepCurve.d.ts +0 -4
  196. package/FunnelChart/funnelStepCurve.js +0 -74
  197. package/esm/FunnelChart/funnelStepCurve.d.ts +0 -4
  198. package/esm/FunnelChart/funnelStepCurve.js +0 -67
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { styled } from '@mui/material/styles';
5
+ import useForkRef from '@mui/utils/useForkRef';
6
+ import useEventCallback from '@mui/utils/useEventCallback';
7
+ import { rafThrottle } from '@mui/x-internals/rafThrottle';
8
+ import { chartAxisZoomSliderHandleClasses, useUtilityClasses } from "./chartAxisZoomSliderHandleClasses.js";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ const Rect = styled('rect')(({
11
+ theme
12
+ }) => ({
13
+ [`&.${chartAxisZoomSliderHandleClasses.root}`]: {
14
+ fill: theme.palette.mode === 'dark' ? (theme.vars || theme).palette.grey[300] : (theme.vars || theme).palette.common.white,
15
+ stroke: theme.palette.mode === 'dark' ? (theme.vars || theme).palette.grey[600] : (theme.vars || theme).palette.grey[500]
16
+ },
17
+ [`&.${chartAxisZoomSliderHandleClasses.horizontal}`]: {
18
+ cursor: 'ew-resize'
19
+ },
20
+ [`&.${chartAxisZoomSliderHandleClasses.vertical}`]: {
21
+ cursor: 'ns-resize'
22
+ }
23
+ }));
24
+ /**
25
+ * Renders the zoom slider handle, which is responsible for resizing the zoom range.
26
+ * @internal
27
+ */
28
+ export const ChartAxisZoomSliderHandle = /*#__PURE__*/React.forwardRef(function ChartPreviewHandle({
29
+ x,
30
+ y,
31
+ width,
32
+ height,
33
+ onResize,
34
+ orientation,
35
+ placement,
36
+ rx = 4,
37
+ ry = 4
38
+ }, forwardedRef) {
39
+ const classes = useUtilityClasses({
40
+ onResize,
41
+ orientation,
42
+ placement
43
+ });
44
+ const handleRef = React.useRef(null);
45
+ const ref = useForkRef(handleRef, forwardedRef);
46
+ const onResizeEvent = useEventCallback(onResize);
47
+ React.useEffect(() => {
48
+ const handle = handleRef.current;
49
+ if (!handle) {
50
+ return;
51
+ }
52
+ const onPointerMove = rafThrottle(event => {
53
+ onResizeEvent(event);
54
+ });
55
+ const onPointerUp = () => {
56
+ handle.removeEventListener('pointermove', onPointerMove);
57
+ handle.removeEventListener('pointerup', onPointerUp);
58
+ };
59
+ const onPointerDown = event => {
60
+ // Prevent text selection when dragging the handle
61
+ event.preventDefault();
62
+ event.stopPropagation();
63
+ handle.setPointerCapture(event.pointerId);
64
+ handle.addEventListener('pointerup', onPointerUp);
65
+ handle.addEventListener('pointermove', onPointerMove);
66
+ };
67
+ handle.addEventListener('pointerdown', onPointerDown);
68
+
69
+ // eslint-disable-next-line consistent-return
70
+ return () => {
71
+ handle.removeEventListener('pointerdown', onPointerDown);
72
+ onPointerMove.clear();
73
+ };
74
+ }, [onResizeEvent, orientation]);
75
+ return /*#__PURE__*/_jsx(Rect, {
76
+ className: classes.root,
77
+ ref: ref,
78
+ x: x,
79
+ y: y,
80
+ width: width,
81
+ height: height,
82
+ rx: rx,
83
+ ry: ry
84
+ });
85
+ });
@@ -0,0 +1,17 @@
1
+ import type { ChartZoomSliderHandleOwnerState } from "./ChartAxisZoomSliderHandle.js";
2
+ export interface ChartAxisZoomSliderHandleClasses {
3
+ /** Styles applied to the root element. */
4
+ root: string;
5
+ /** Styles applied to the root element when it is horizontal. */
6
+ horizontal: string;
7
+ /** Styles applied to the root element when it is vertical. */
8
+ vertical: string;
9
+ /** Styles applied to the root element when it is a start handle. */
10
+ start: string;
11
+ /** Styles applied to the root element when it is an end handle. */
12
+ end: string;
13
+ }
14
+ export type ChartAxisZoomSliderHandleClassKey = keyof ChartAxisZoomSliderHandleClasses;
15
+ export declare const chartAxisZoomSliderHandleClasses: ChartAxisZoomSliderHandleClasses;
16
+ export declare function getAxisZoomSliderHandleUtilityClass(slot: string): string;
17
+ export declare const useUtilityClasses: (ownerState: ChartZoomSliderHandleOwnerState) => Record<"root", string>;
@@ -0,0 +1,17 @@
1
+ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
2
+ import composeClasses from '@mui/utils/composeClasses';
3
+ import generateUtilityClass from '@mui/utils/generateUtilityClass';
4
+ export const chartAxisZoomSliderHandleClasses = generateUtilityClasses('MuiChartAxisZoomSliderHandle', ['root', 'horizontal', 'vertical', 'start', 'end']);
5
+ export function getAxisZoomSliderHandleUtilityClass(slot) {
6
+ return generateUtilityClass('MuiChartAxisZoomSliderHandle', slot);
7
+ }
8
+ export const useUtilityClasses = ownerState => {
9
+ const {
10
+ orientation,
11
+ placement
12
+ } = ownerState;
13
+ const slots = {
14
+ root: ['root', orientation === 'horizontal' ? 'horizontal' : 'vertical', placement === 'start' ? 'start' : 'end']
15
+ };
16
+ return composeClasses(slots, getAxisZoomSliderHandleUtilityClass);
17
+ };
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare function ChartsToolbarPro(): React.JSX.Element | null;
@@ -0,0 +1,24 @@
1
+ import { Toolbar } from '@mui/x-charts/Toolbar';
2
+ import * as React from 'react';
3
+ import { useChartContext, useSelector } from '@mui/x-charts/internals';
4
+ import { selectorChartZoomIsEnabled } from "../internals/plugins/useChartProZoom/index.js";
5
+ import { ChartsToolbarZoomInButton } from "./internal/ChartsToolbarZoomInButton.js";
6
+ import { ChartsToolbarZoomOutButton } from "./internal/ChartsToolbarZoomOutButton.js";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ export function ChartsToolbarPro() {
9
+ const {
10
+ store
11
+ } = useChartContext();
12
+ const isZoomEnabled = useSelector(store, selectorChartZoomIsEnabled);
13
+ const children = [];
14
+ if (isZoomEnabled) {
15
+ children.push(/*#__PURE__*/_jsx(ChartsToolbarZoomInButton, {}, "zoom-in"));
16
+ children.push(/*#__PURE__*/_jsx(ChartsToolbarZoomOutButton, {}, "zoom-out"));
17
+ }
18
+ if (children.length === 0) {
19
+ return null;
20
+ }
21
+ return /*#__PURE__*/_jsx(Toolbar, {
22
+ children: children
23
+ });
24
+ }
@@ -0,0 +1 @@
1
+ export * from "./ChartsToolbarPro.js";
@@ -0,0 +1 @@
1
+ export * from "./ChartsToolbarPro.js";
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import { ChartsSlotsPro } from "../../internals/material/index.js";
3
+ type ChartsToolbarZoomInButtonSlots = Partial<Pick<ChartsSlotsPro, 'baseTooltip' | 'zoomInIcon'>>;
4
+ type ChartsToolbarZoomInButtonSlotProps = { [K in keyof Required<ChartsToolbarZoomInButtonSlots>]: React.ComponentProps<Required<ChartsToolbarZoomInButtonSlots>[K]> };
5
+ interface ChartsToolbarZoomInButtonProps {
6
+ slots?: ChartsToolbarZoomInButtonSlots;
7
+ slotProps?: ChartsToolbarZoomInButtonSlotProps;
8
+ }
9
+ export declare function ChartsToolbarZoomInButton({
10
+ slots,
11
+ slotProps
12
+ }: ChartsToolbarZoomInButtonProps): React.JSX.Element;
13
+ export {};
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+
3
+ import _extends from "@babel/runtime/helpers/esm/extends";
4
+ import * as React from 'react';
5
+ import { ToolbarButton } from '@mui/x-charts/Toolbar';
6
+ import { useChartContext } from '@mui/x-charts/internals';
7
+ import { useChartsLocalization } from '@mui/x-charts/hooks';
8
+ import { defaultSlotsMaterial } from "../../internals/material/index.js";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ export function ChartsToolbarZoomInButton({
11
+ slots,
12
+ slotProps
13
+ }) {
14
+ const {
15
+ instance
16
+ } = useChartContext();
17
+ const ZoomInIcon = slots?.zoomInIcon ?? defaultSlotsMaterial.zoomInIcon;
18
+ const Tooltip = slots?.baseTooltip ?? defaultSlotsMaterial.baseTooltip;
19
+ const {
20
+ localeText
21
+ } = useChartsLocalization();
22
+ return /*#__PURE__*/_jsx(Tooltip, {
23
+ title: localeText.zoomIn,
24
+ children: /*#__PURE__*/_jsx(ToolbarButton, {
25
+ onClick: () => instance.zoomIn(),
26
+ children: /*#__PURE__*/_jsx(ZoomInIcon, _extends({}, slotProps?.zoomInIcon))
27
+ })
28
+ });
29
+ }
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import { ChartsSlotsPro } from "../../internals/material/index.js";
3
+ type ChartsToolbarZoomOutButtonSlots = Partial<Pick<ChartsSlotsPro, 'baseTooltip' | 'zoomOutIcon'>>;
4
+ type ChartsToolbarZoomOutButtonSlotProps = { [K in keyof Required<ChartsToolbarZoomOutButtonSlots>]: React.ComponentProps<Required<ChartsToolbarZoomOutButtonSlots>[K]> };
5
+ interface ChartsToolbarZoomOutButtonProps {
6
+ slots?: ChartsToolbarZoomOutButtonSlots;
7
+ slotProps?: ChartsToolbarZoomOutButtonSlotProps;
8
+ }
9
+ export declare function ChartsToolbarZoomOutButton({
10
+ slots,
11
+ slotProps
12
+ }: ChartsToolbarZoomOutButtonProps): React.JSX.Element;
13
+ export {};
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+
3
+ import _extends from "@babel/runtime/helpers/esm/extends";
4
+ import * as React from 'react';
5
+ import { ToolbarButton } from '@mui/x-charts/Toolbar';
6
+ import { useChartContext } from '@mui/x-charts/internals';
7
+ import { useChartsLocalization } from '@mui/x-charts/hooks';
8
+ import { defaultSlotsMaterial } from "../../internals/material/index.js";
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ export function ChartsToolbarZoomOutButton({
11
+ slots,
12
+ slotProps
13
+ }) {
14
+ const {
15
+ instance
16
+ } = useChartContext();
17
+ const ZoomOutIcon = slots?.zoomOutIcon ?? defaultSlotsMaterial.zoomOutIcon;
18
+ const Tooltip = slots?.baseTooltip ?? defaultSlotsMaterial.baseTooltip;
19
+ const {
20
+ localeText
21
+ } = useChartsLocalization();
22
+ return /*#__PURE__*/_jsx(Tooltip, {
23
+ title: localeText.zoomOut,
24
+ children: /*#__PURE__*/_jsx(ToolbarButton, {
25
+ onClick: () => instance.zoomOut(),
26
+ children: /*#__PURE__*/_jsx(ZoomOutIcon, _extends({}, slotProps?.zoomOutIcon))
27
+ })
28
+ });
29
+ }
@@ -8,7 +8,6 @@ import { ChartsOverlay } from '@mui/x-charts/ChartsOverlay';
8
8
  import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip';
9
9
  import { ChartsWrapper } from '@mui/x-charts/internals';
10
10
  import { ChartsLegend } from '@mui/x-charts/ChartsLegend';
11
- import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath';
12
11
  import { ChartsSurface } from '@mui/x-charts/ChartsSurface';
13
12
  import { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight';
14
13
  import { ChartsAxis } from '@mui/x-charts/ChartsAxis';
@@ -31,9 +30,7 @@ const FunnelChart = /*#__PURE__*/React.forwardRef(function FunnelChart(props, re
31
30
  funnelPlotProps,
32
31
  overlayProps,
33
32
  legendProps,
34
- clipPathGroupProps,
35
33
  chartsAxisProps,
36
- clipPathProps,
37
34
  chartsWrapperProps,
38
35
  axisHighlightProps,
39
36
  children
@@ -47,11 +44,9 @@ const FunnelChart = /*#__PURE__*/React.forwardRef(function FunnelChart(props, re
47
44
  seriesConfig: seriesConfig,
48
45
  children: /*#__PURE__*/_jsxs(ChartsWrapper, _extends({}, chartsWrapperProps, {
49
46
  children: [!themedProps.hideLegend && /*#__PURE__*/_jsx(ChartsLegend, _extends({}, legendProps)), /*#__PURE__*/_jsxs(ChartsSurface, _extends({}, chartsSurfaceProps, {
50
- children: [/*#__PURE__*/_jsxs("g", _extends({}, clipPathGroupProps, {
51
- children: [/*#__PURE__*/_jsx(FunnelPlot, _extends({}, funnelPlotProps)), /*#__PURE__*/_jsx(ChartsOverlay, _extends({}, overlayProps)), /*#__PURE__*/_jsx(ChartsAxisHighlight, _extends({}, axisHighlightProps))]
52
- })), !themedProps.loading && /*#__PURE__*/_jsx(Tooltip, _extends({}, themedProps.slotProps?.tooltip, {
47
+ children: [/*#__PURE__*/_jsx(FunnelPlot, _extends({}, funnelPlotProps)), /*#__PURE__*/_jsx(ChartsOverlay, _extends({}, overlayProps)), /*#__PURE__*/_jsx(ChartsAxisHighlight, _extends({}, axisHighlightProps)), !themedProps.loading && /*#__PURE__*/_jsx(Tooltip, _extends({}, themedProps.slotProps?.tooltip, {
53
48
  trigger: "item"
54
- })), /*#__PURE__*/_jsx(ChartsAxis, _extends({}, chartsAxisProps)), /*#__PURE__*/_jsx(ChartsClipPath, _extends({}, clipPathProps)), children]
49
+ })), /*#__PURE__*/_jsx(ChartsAxis, _extends({}, chartsAxisProps)), children]
55
50
  }))]
56
51
  }))
57
52
  }));
@@ -63,6 +58,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
63
58
  // ----------------------------------------------------------------------
64
59
  apiRef: PropTypes.shape({
65
60
  current: PropTypes.shape({
61
+ exportAsImage: PropTypes.func.isRequired,
66
62
  exportAsPrint: PropTypes.func.isRequired,
67
63
  setZoomData: PropTypes.func.isRequired
68
64
  })
@@ -176,6 +172,11 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
176
172
  * @default false
177
173
  */
178
174
  disableAxisListener: PropTypes.bool,
175
+ /**
176
+ * The gap, in pixels, between funnel sections.
177
+ * @default 0
178
+ */
179
+ gap: PropTypes.number,
179
180
  /**
180
181
  * The height of the chart in px. If not defined, it takes the height of the parent element.
181
182
  */
@@ -232,7 +233,7 @@ process.env.NODE_ENV !== "production" ? FunnelChart.propTypes = {
232
233
  * The function called for onClick events.
233
234
  * The second argument contains information about all line/bar elements at the current mouse position.
234
235
  * @param {MouseEvent} event The mouse event recorded on the `<svg/>` element.
235
- * @param {null | AxisData} data The data about the clicked axis and items associated with it.
236
+ * @param {null | ChartsAxisData} data The data about the clicked axis and items associated with it.
236
237
  */
237
238
  onAxisClick: PropTypes.func,
238
239
  /**
@@ -2,6 +2,11 @@ import * as React from 'react';
2
2
  import { FunnelItemIdentifier } from "./funnel.types.js";
3
3
  import { FunnelPlotSlotExtension } from "./funnelPlotSlots.types.js";
4
4
  export interface FunnelPlotProps extends FunnelPlotSlotExtension {
5
+ /**
6
+ * The gap, in pixels, between funnel sections.
7
+ * @default 0
8
+ */
9
+ gap?: number;
5
10
  /**
6
11
  * Callback fired when a funnel item is clicked.
7
12
  * @param {React.MouseEvent<SVGElement, MouseEvent>} event The event source of the callback.
@@ -1,29 +1,20 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
- const _excluded = ["onItemClick"];
3
+ const _excluded = ["onItemClick", "gap"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { line as d3Line } from '@mui/x-charts-vendor/d3-shape';
7
- import { getCurveFactory, cartesianSeriesTypes } from '@mui/x-charts/internals';
7
+ import { cartesianSeriesTypes } from '@mui/x-charts/internals';
8
8
  import { useXAxes, useYAxes } from '@mui/x-charts/hooks';
9
9
  import { useTheme } from '@mui/material/styles';
10
10
  import { FunnelSection } from "./FunnelSection.js";
11
11
  import { alignLabel, positionLabel } from "./labelUtils.js";
12
- import { funnelHorizontalStepCurve, funnelVerticalStepCurve } from "./funnelStepCurve.js";
13
12
  import { useFunnelSeriesContext } from "../hooks/useFunnelSeries.js";
13
+ import { getFunnelCurve } from "./curves/index.js";
14
14
  import { createElement as _createElement } from "react";
15
15
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
16
  cartesianSeriesTypes.addType('funnel');
17
- const getFunnelCurve = (curve, isHorizontal) => {
18
- if (curve === 'step') {
19
- return isHorizontal ? funnelHorizontalStepCurve : funnelVerticalStepCurve;
20
- }
21
- if (curve === 'bump') {
22
- return isHorizontal ? getCurveFactory('bumpX') : getCurveFactory('bumpY');
23
- }
24
- return getCurveFactory(curve ?? 'linear');
25
- };
26
- const useAggregatedData = () => {
17
+ const useAggregatedData = gap => {
27
18
  const seriesData = useFunnelSeriesContext();
28
19
  const {
29
20
  xAxis,
@@ -55,7 +46,6 @@ const useAggregatedData = () => {
55
46
  const bandWidth = (isXAxisBand || isYAxisBand) && baseScaleConfig.scale?.bandwidth() || 0;
56
47
  const xScale = xAxis[xAxisId].scale;
57
48
  const yScale = yAxis[yAxisId].scale;
58
- const curve = getFunnelCurve(currentSeries.curve, isHorizontal);
59
49
  const xPosition = (value, bandIndex, stackOffset, useBand) => {
60
50
  if (isXAxisBand) {
61
51
  const position = xScale(bandIndex);
@@ -70,7 +60,17 @@ const useAggregatedData = () => {
70
60
  }
71
61
  return yScale(isHorizontal ? value : value + (stackOffset || 0));
72
62
  };
73
- return currentSeries.dataPoints.map((values, dataIndex) => {
63
+ const allY = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => yPosition(v.y, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
64
+ const allX = currentSeries.dataPoints.flatMap((d, dataIndex) => d.flatMap(v => xPosition(v.x, baseScaleConfig.data?.[dataIndex], v.stackOffset, v.useBandWidth)));
65
+ const minPoint = {
66
+ x: Math.min(...allX),
67
+ y: Math.min(...allY)
68
+ };
69
+ const maxPoint = {
70
+ x: Math.max(...allX),
71
+ y: Math.max(...allY)
72
+ };
73
+ return currentSeries.dataPoints.flatMap((values, dataIndex) => {
74
74
  const color = currentSeries.data[dataIndex].color;
75
75
  const id = `${seriesId}-${dataIndex}`;
76
76
  const sectionLabel = typeof currentSeries.sectionLabel === 'function' ? currentSeries.sectionLabel({
@@ -78,6 +78,15 @@ const useAggregatedData = () => {
78
78
  seriesId,
79
79
  value: currentSeries.data[dataIndex].value
80
80
  }) : currentSeries.sectionLabel;
81
+ const curve = getFunnelCurve(currentSeries.curve, {
82
+ isHorizontal,
83
+ gap,
84
+ position: dataIndex,
85
+ sections: currentSeries.dataPoints.length,
86
+ borderRadius: currentSeries.borderRadius,
87
+ min: minPoint,
88
+ max: maxPoint
89
+ });
81
90
  const line = d3Line().x(d => xPosition(d.x, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).y(d => yPosition(d.y, baseScaleConfig.data?.[dataIndex], d.stackOffset, d.useBandWidth)).curve(curve);
82
91
  return {
83
92
  d: line(values),
@@ -85,6 +94,7 @@ const useAggregatedData = () => {
85
94
  id,
86
95
  seriesId,
87
96
  dataIndex,
97
+ variant: currentSeries.variant,
88
98
  label: sectionLabel !== false && _extends({}, positionLabel(_extends({}, sectionLabel, {
89
99
  xPosition,
90
100
  yPosition,
@@ -101,29 +111,32 @@ const useAggregatedData = () => {
101
111
  });
102
112
  });
103
113
  return result.flat();
104
- }, [seriesData, xAxis, xAxisIds, yAxis, yAxisIds]);
114
+ }, [seriesData, xAxis, xAxisIds, yAxis, yAxisIds, gap]);
105
115
  return allData;
106
116
  };
107
117
  function FunnelPlot(props) {
108
118
  const {
109
- onItemClick
119
+ onItemClick,
120
+ gap
110
121
  } = props,
111
122
  other = _objectWithoutPropertiesLoose(props, _excluded);
112
123
  const theme = useTheme();
113
- const data = useAggregatedData();
124
+ const data = useAggregatedData(gap);
114
125
  return /*#__PURE__*/_jsxs(React.Fragment, {
115
126
  children: [data.map(({
116
127
  d,
117
128
  color,
118
129
  id,
119
130
  seriesId,
120
- dataIndex
131
+ dataIndex,
132
+ variant
121
133
  }) => /*#__PURE__*/_createElement(FunnelSection, _extends({}, other, {
122
134
  d: d,
123
135
  color: color,
124
136
  key: id,
125
137
  dataIndex: dataIndex,
126
138
  seriesId: seriesId,
139
+ variant: variant,
127
140
  onClick: onItemClick && (event => {
128
141
  onItemClick(event, {
129
142
  type: 'funnel',
@@ -164,6 +177,11 @@ process.env.NODE_ENV !== "production" ? FunnelPlot.propTypes = {
164
177
  // | These PropTypes are generated from the TypeScript type definitions |
165
178
  // | To update them edit the TypeScript types and run "pnpm proptypes" |
166
179
  // ----------------------------------------------------------------------
180
+ /**
181
+ * The gap, in pixels, between funnel sections.
182
+ * @default 0
183
+ */
184
+ gap: PropTypes.number,
167
185
  /**
168
186
  * Callback fired when a funnel item is clicked.
169
187
  * @param {React.MouseEvent<SVGElement, MouseEvent>} event The event source of the callback.
@@ -6,6 +6,7 @@ export interface FunnelSectionProps extends Omit<React.SVGProps<SVGPathElement>,
6
6
  dataIndex: number;
7
7
  color: string;
8
8
  classes?: Partial<FunnelSectionClasses>;
9
+ variant?: 'filled' | 'outlined';
9
10
  }
10
11
  export declare const FunnelSectionPath: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, React.SVGProps<SVGPathElement>, {}>;
11
12
  /**
@@ -2,7 +2,7 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
5
- const _excluded = ["seriesId", "dataIndex", "classes", "color", "onClick", "className"];
5
+ const _excluded = ["seriesId", "dataIndex", "classes", "color", "onClick", "className", "variant"];
6
6
  import * as React from 'react';
7
7
  import { styled } from '@mui/material/styles';
8
8
  import { useInteractionItemProps, consumeSlots } from '@mui/x-charts/internals';
@@ -11,7 +11,7 @@ import clsx from 'clsx';
11
11
  import { useUtilityClasses } from "./funnelSectionClasses.js";
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
13
  export const FunnelSectionPath = styled('path')(() => ({
14
- transition: 'opacity 0.2s ease-in, fill 0.2s ease-in'
14
+ transition: 'opacity 0.2s ease-in, fill 0.2s ease-in, fill-opacity 0.2s ease-in, filter 0.2s ease-in'
15
15
  }));
16
16
 
17
17
  /**
@@ -26,7 +26,8 @@ const FunnelSection = consumeSlots('MuiFunnelSection', 'funnelSection', {
26
26
  classes,
27
27
  color,
28
28
  onClick,
29
- className
29
+ className,
30
+ variant = 'filled'
30
31
  } = props,
31
32
  other = _objectWithoutPropertiesLoose(props, _excluded);
32
33
  const interactionProps = useInteractionItemProps({
@@ -41,14 +42,18 @@ const FunnelSection = consumeSlots('MuiFunnelSection', 'funnelSection', {
41
42
  seriesId,
42
43
  dataIndex
43
44
  });
45
+ const isOutlined = variant === 'outlined';
44
46
  return /*#__PURE__*/_jsx(FunnelSectionPath, _extends({}, interactionProps, {
45
- filter: isHighlighted ? 'brightness(120%)' : undefined,
46
- opacity: isFaded ? 0.3 : 1,
47
+ filter: isHighlighted && !isOutlined ? 'brightness(120%)' : undefined,
48
+ opacity: isFaded && !isOutlined ? 0.3 : 1,
47
49
  fill: color,
48
- stroke: "none",
50
+ stroke: isOutlined ? color : 'none',
51
+ fillOpacity: isOutlined && !isHighlighted ? 0.4 : 1,
52
+ strokeOpacity: 1,
53
+ strokeWidth: isOutlined ? 1.5 : 0,
49
54
  cursor: onClick ? 'pointer' : 'unset',
50
55
  onClick: onClick,
51
- className: clsx(classes?.root, className, isHighlighted && classes?.highlighted, isFaded && classes?.faded)
56
+ className: clsx(classes?.root, className, isOutlined ? classes?.outlined : classes?.filled, isHighlighted && classes?.highlighted, isFaded && classes?.faded)
52
57
  }, other, {
53
58
  ref: ref
54
59
  }));
@@ -0,0 +1,8 @@
1
+ import { Point } from "./curve.types.js";
2
+ /**
3
+ * Draws a polygon with rounded corners
4
+ * @param {CanvasRenderingContext2D} ctx The canvas context
5
+ * @param {Array} points A list of `{x, y}` points
6
+ * @param {number} radius how much to round the corners
7
+ */
8
+ export declare function borderRadiusPolygon(ctx: CanvasRenderingContext2D, points: Point[], radius: number | number[]): void;
@@ -0,0 +1,36 @@
1
+ const distance = (p1, p2) => Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
2
+ const lerp = (a, b, x) => a + (b - a) * x;
3
+ const lerp2D = (p1, p2, t) => ({
4
+ x: lerp(p1.x, p2.x, t),
5
+ y: lerp(p1.y, p2.y, t)
6
+ });
7
+
8
+ /**
9
+ * Draws a polygon with rounded corners
10
+ * @param {CanvasRenderingContext2D} ctx The canvas context
11
+ * @param {Array} points A list of `{x, y}` points
12
+ * @param {number} radius how much to round the corners
13
+ */
14
+ export function borderRadiusPolygon(ctx, points, radius) {
15
+ const numPoints = points.length;
16
+ radius = Array.isArray(radius) ? radius : Array(numPoints).fill(radius);
17
+ const corners = [];
18
+ for (let i = 0; i < numPoints; i += 1) {
19
+ const lastPoint = points[i];
20
+ const thisPoint = points[(i + 1) % numPoints];
21
+ const nextPoint = points[(i + 2) % numPoints];
22
+ const lastEdgeLength = distance(lastPoint, thisPoint);
23
+ const lastOffsetDistance = Math.min(lastEdgeLength / 2, radius[i] ?? 0);
24
+ const start = lerp2D(thisPoint, lastPoint, lastOffsetDistance / lastEdgeLength);
25
+ const nextEdgeLength = distance(nextPoint, thisPoint);
26
+ const nextOffsetDistance = Math.min(nextEdgeLength / 2, radius[i] ?? 0);
27
+ const end = lerp2D(thisPoint, nextPoint, nextOffsetDistance / nextEdgeLength);
28
+ corners.push([start, thisPoint, end]);
29
+ }
30
+ ctx.moveTo(corners[0][0].x, corners[0][0].y);
31
+ for (const [start, ctrl, end] of corners) {
32
+ ctx.lineTo(start.x, start.y);
33
+ ctx.quadraticCurveTo(ctrl.x, ctrl.y, end.x, end.y);
34
+ }
35
+ ctx.closePath();
36
+ }
@@ -0,0 +1,27 @@
1
+ import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
+ import { CurveOptions } from "./curve.types.js";
3
+ /**
4
+ * This is a custom "bump" curve generator.
5
+ * It draws smooth curves for the 4 provided points,
6
+ * with the option to add a gap between sections while also properly handling the border radius.
7
+ *
8
+ * The implementation is based on the d3-shape bump curve generator.
9
+ * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/bump.js
10
+ */
11
+ export declare class Bump implements CurveGenerator {
12
+ private context;
13
+ private x;
14
+ private y;
15
+ private currentPoint;
16
+ private isHorizontal;
17
+ private gap;
18
+ constructor(context: CanvasRenderingContext2D, {
19
+ isHorizontal,
20
+ gap
21
+ }: CurveOptions);
22
+ areaStart(): void;
23
+ areaEnd(): void;
24
+ lineStart(): void;
25
+ lineEnd(): void;
26
+ point(x: number, y: number): void;
27
+ }
@@ -0,0 +1,74 @@
1
+ /* eslint-disable class-methods-use-this */
2
+
3
+ /**
4
+ * This is a custom "bump" curve generator.
5
+ * It draws smooth curves for the 4 provided points,
6
+ * with the option to add a gap between sections while also properly handling the border radius.
7
+ *
8
+ * The implementation is based on the d3-shape bump curve generator.
9
+ * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/bump.js
10
+ */
11
+ export class Bump {
12
+ constructor(context, {
13
+ isHorizontal,
14
+ gap
15
+ }) {
16
+ this.context = void 0;
17
+ this.x = NaN;
18
+ this.y = NaN;
19
+ this.currentPoint = 0;
20
+ this.isHorizontal = false;
21
+ this.gap = 0;
22
+ this.context = context;
23
+ this.isHorizontal = isHorizontal ?? false;
24
+ this.gap = (gap ?? 0) / 2;
25
+ }
26
+ areaStart() {}
27
+ areaEnd() {}
28
+ lineStart() {}
29
+ lineEnd() {}
30
+ point(x, y) {
31
+ x = +x;
32
+ y = +y;
33
+
34
+ // 0 is the top-left corner.
35
+ if (this.isHorizontal) {
36
+ if (this.currentPoint === 0) {
37
+ this.context.moveTo(x + this.gap, y);
38
+ this.context.lineTo(x + this.gap, y);
39
+ } else if (this.currentPoint === 1) {
40
+ this.context.bezierCurveTo((this.x + x) / 2, this.y, (this.x + x) / 2, y, x - this.gap, y);
41
+ } else if (this.currentPoint === 2) {
42
+ this.context.lineTo(x - this.gap, y);
43
+ } else {
44
+ this.context.bezierCurveTo((this.x + x) / 2, this.y, (this.x + x) / 2, y, x + this.gap, y);
45
+ }
46
+ if (this.currentPoint === 3) {
47
+ this.context.closePath();
48
+ }
49
+ this.currentPoint += 1;
50
+ this.x = x;
51
+ this.y = y;
52
+ return;
53
+ }
54
+
55
+ // 0 is the top-right corner.
56
+ if (this.currentPoint === 0) {
57
+ // X from Y
58
+ this.context.moveTo(x, y + this.gap);
59
+ this.context.lineTo(x, y + this.gap);
60
+ } else if (this.currentPoint === 1) {
61
+ this.context.bezierCurveTo(this.x, (this.y + y) / 2, x, (this.y + y) / 2, x, y - this.gap);
62
+ } else if (this.currentPoint === 2) {
63
+ this.context.lineTo(x, y - this.gap);
64
+ } else {
65
+ this.context.bezierCurveTo(this.x, (this.y + y) / 2, x, (this.y + y) / 2, x, y + this.gap);
66
+ }
67
+ if (this.currentPoint === 3) {
68
+ this.context.closePath();
69
+ }
70
+ this.currentPoint += 1;
71
+ this.x = x;
72
+ this.y = y;
73
+ }
74
+ }