@mui/x-charts-pro 8.2.0 → 8.3.1

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 (154) hide show
  1. package/BarChartPro/BarChartPro.d.ts +7 -1
  2. package/BarChartPro/BarChartPro.js +60 -4
  3. package/CHANGELOG.md +199 -6
  4. package/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  5. package/ChartZoomSlider/ChartZoomSlider.d.ts +5 -0
  6. package/ChartZoomSlider/ChartZoomSlider.js +47 -0
  7. package/ChartZoomSlider/index.d.ts +2 -0
  8. package/ChartZoomSlider/index.js +27 -0
  9. package/ChartZoomSlider/internals/ChartAxisZoomSlider.d.ts +23 -0
  10. package/ChartZoomSlider/internals/ChartAxisZoomSlider.js +348 -0
  11. package/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.d.ts +12 -0
  12. package/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.js +92 -0
  13. package/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.d.ts +17 -0
  14. package/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.js +27 -0
  15. package/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -0
  16. package/ChartsToolbarPro/ChartsToolbarPro.js +31 -0
  17. package/ChartsToolbarPro/index.d.ts +1 -0
  18. package/ChartsToolbarPro/index.js +16 -0
  19. package/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.d.ts +13 -0
  20. package/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.js +36 -0
  21. package/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.d.ts +13 -0
  22. package/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.js +36 -0
  23. package/FunnelChart/FunnelChart.js +2 -7
  24. package/FunnelChart/FunnelPlot.js +24 -3
  25. package/FunnelChart/FunnelSection.d.ts +1 -0
  26. package/FunnelChart/FunnelSection.js +12 -7
  27. package/FunnelChart/curves/borderRadiusPolygon.d.ts +8 -0
  28. package/FunnelChart/curves/borderRadiusPolygon.js +42 -0
  29. package/FunnelChart/curves/bump.d.ts +8 -5
  30. package/FunnelChart/curves/bump.js +21 -22
  31. package/FunnelChart/curves/curve.types.d.ts +33 -3
  32. package/FunnelChart/curves/getFunnelCurve.d.ts +2 -2
  33. package/FunnelChart/curves/getFunnelCurve.js +12 -4
  34. package/FunnelChart/curves/linear.d.ts +17 -9
  35. package/FunnelChart/curves/linear.js +62 -87
  36. package/FunnelChart/curves/pyramid.d.ts +34 -0
  37. package/FunnelChart/curves/pyramid.js +127 -0
  38. package/FunnelChart/curves/step-pyramid.d.ts +31 -0
  39. package/FunnelChart/curves/step-pyramid.js +107 -0
  40. package/FunnelChart/curves/step.d.ts +32 -0
  41. package/FunnelChart/curves/step.js +88 -0
  42. package/FunnelChart/curves/utils.d.ts +4 -0
  43. package/FunnelChart/curves/utils.js +29 -0
  44. package/FunnelChart/funnel.types.d.ts +23 -2
  45. package/FunnelChart/funnelSectionClasses.d.ts +5 -1
  46. package/FunnelChart/funnelSectionClasses.js +5 -2
  47. package/FunnelChart/seriesConfig/getSeriesWithDefaultValues.js +1 -0
  48. package/FunnelChart/useFunnelChartProps.d.ts +0 -5
  49. package/FunnelChart/useFunnelChartProps.js +0 -11
  50. package/Heatmap/Heatmap.d.ts +3 -3
  51. package/Heatmap/Heatmap.js +2 -20
  52. package/LineChartPro/LineChartPro.d.ts +7 -1
  53. package/LineChartPro/LineChartPro.js +60 -4
  54. package/ScatterChartPro/ScatterChartPro.d.ts +7 -1
  55. package/ScatterChartPro/ScatterChartPro.js +60 -4
  56. package/esm/BarChartPro/BarChartPro.d.ts +7 -1
  57. package/esm/BarChartPro/BarChartPro.js +60 -4
  58. package/esm/ChartDataProviderPro/ChartDataProviderPro.js +1 -1
  59. package/esm/ChartZoomSlider/ChartZoomSlider.d.ts +5 -0
  60. package/esm/ChartZoomSlider/ChartZoomSlider.js +41 -0
  61. package/esm/ChartZoomSlider/index.d.ts +2 -0
  62. package/esm/ChartZoomSlider/index.js +2 -0
  63. package/esm/ChartZoomSlider/internals/ChartAxisZoomSlider.d.ts +23 -0
  64. package/esm/ChartZoomSlider/internals/ChartAxisZoomSlider.js +339 -0
  65. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.d.ts +12 -0
  66. package/esm/ChartZoomSlider/internals/ChartAxisZoomSliderHandle.js +85 -0
  67. package/esm/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.d.ts +17 -0
  68. package/esm/ChartZoomSlider/internals/chartAxisZoomSliderHandleClasses.js +17 -0
  69. package/esm/ChartsToolbarPro/ChartsToolbarPro.d.ts +2 -0
  70. package/esm/ChartsToolbarPro/ChartsToolbarPro.js +24 -0
  71. package/esm/ChartsToolbarPro/index.d.ts +1 -0
  72. package/esm/ChartsToolbarPro/index.js +1 -0
  73. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.d.ts +13 -0
  74. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomInButton.js +29 -0
  75. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.d.ts +13 -0
  76. package/esm/ChartsToolbarPro/internal/ChartsToolbarZoomOutButton.js +29 -0
  77. package/esm/FunnelChart/FunnelChart.js +2 -7
  78. package/esm/FunnelChart/FunnelPlot.js +24 -3
  79. package/esm/FunnelChart/FunnelSection.d.ts +1 -0
  80. package/esm/FunnelChart/FunnelSection.js +12 -7
  81. package/esm/FunnelChart/curves/borderRadiusPolygon.d.ts +8 -0
  82. package/esm/FunnelChart/curves/borderRadiusPolygon.js +36 -0
  83. package/esm/FunnelChart/curves/bump.d.ts +8 -5
  84. package/esm/FunnelChart/curves/bump.js +21 -22
  85. package/esm/FunnelChart/curves/curve.types.d.ts +33 -3
  86. package/esm/FunnelChart/curves/getFunnelCurve.d.ts +2 -2
  87. package/esm/FunnelChart/curves/getFunnelCurve.js +12 -4
  88. package/esm/FunnelChart/curves/linear.d.ts +17 -9
  89. package/esm/FunnelChart/curves/linear.js +62 -86
  90. package/esm/FunnelChart/curves/pyramid.d.ts +34 -0
  91. package/esm/FunnelChart/curves/pyramid.js +121 -0
  92. package/esm/FunnelChart/curves/step-pyramid.d.ts +31 -0
  93. package/esm/FunnelChart/curves/step-pyramid.js +101 -0
  94. package/esm/FunnelChart/curves/step.d.ts +32 -0
  95. package/esm/FunnelChart/curves/step.js +82 -0
  96. package/esm/FunnelChart/curves/utils.d.ts +4 -0
  97. package/esm/FunnelChart/curves/utils.js +19 -0
  98. package/esm/FunnelChart/funnel.types.d.ts +23 -2
  99. package/esm/FunnelChart/funnelSectionClasses.d.ts +5 -1
  100. package/esm/FunnelChart/funnelSectionClasses.js +5 -2
  101. package/esm/FunnelChart/seriesConfig/getSeriesWithDefaultValues.js +1 -0
  102. package/esm/FunnelChart/useFunnelChartProps.d.ts +0 -5
  103. package/esm/FunnelChart/useFunnelChartProps.js +0 -11
  104. package/esm/Heatmap/Heatmap.d.ts +3 -3
  105. package/esm/Heatmap/Heatmap.js +2 -20
  106. package/esm/LineChartPro/LineChartPro.d.ts +7 -1
  107. package/esm/LineChartPro/LineChartPro.js +60 -4
  108. package/esm/ScatterChartPro/ScatterChartPro.d.ts +7 -1
  109. package/esm/ScatterChartPro/ScatterChartPro.js +60 -4
  110. package/esm/index.d.ts +4 -1
  111. package/esm/index.js +4 -3
  112. package/esm/internals/material/icons.d.ts +3 -0
  113. package/esm/internals/material/icons.js +13 -0
  114. package/esm/internals/material/index.d.ts +4 -0
  115. package/esm/internals/material/index.js +12 -0
  116. package/esm/internals/plugins/useChartProZoom/calculateZoom.d.ts +23 -0
  117. package/esm/internals/plugins/useChartProZoom/calculateZoom.js +32 -0
  118. package/esm/internals/plugins/useChartProZoom/useChartProZoom.d.ts +1 -1
  119. package/esm/internals/plugins/useChartProZoom/useChartProZoom.js +45 -3
  120. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +63 -11
  121. package/esm/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +3 -2
  122. package/esm/internals/plugins/useChartProZoom/useChartProZoom.types.d.ts +17 -2
  123. package/esm/internals/slots/chartBaseSlotProps.d.ts +10 -0
  124. package/esm/internals/slots/chartBaseSlotProps.js +1 -0
  125. package/esm/internals/slots/chartsBaseSlots.d.ts +6 -0
  126. package/esm/internals/slots/chartsBaseSlots.js +1 -0
  127. package/esm/internals/slots/chartsIconSlots.d.ts +14 -0
  128. package/esm/internals/slots/chartsIconSlots.js +1 -0
  129. package/esm/typeOverloads/modules.d.ts +1 -1
  130. package/index.d.ts +4 -1
  131. package/index.js +23 -1
  132. package/internals/material/icons.d.ts +3 -0
  133. package/internals/material/icons.js +20 -0
  134. package/internals/material/index.d.ts +4 -0
  135. package/internals/material/index.js +19 -0
  136. package/internals/plugins/useChartProZoom/calculateZoom.d.ts +23 -0
  137. package/internals/plugins/useChartProZoom/calculateZoom.js +39 -0
  138. package/internals/plugins/useChartProZoom/useChartProZoom.d.ts +1 -1
  139. package/internals/plugins/useChartProZoom/useChartProZoom.js +44 -2
  140. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.d.ts +63 -11
  141. package/internals/plugins/useChartProZoom/useChartProZoom.selectors.js +3 -2
  142. package/internals/plugins/useChartProZoom/useChartProZoom.types.d.ts +17 -2
  143. package/internals/slots/chartBaseSlotProps.d.ts +10 -0
  144. package/internals/slots/chartBaseSlotProps.js +5 -0
  145. package/internals/slots/chartsBaseSlots.d.ts +6 -0
  146. package/internals/slots/chartsBaseSlots.js +5 -0
  147. package/internals/slots/chartsIconSlots.d.ts +14 -0
  148. package/internals/slots/chartsIconSlots.js +5 -0
  149. package/package.json +7 -7
  150. package/typeOverloads/modules.d.ts +1 -1
  151. package/FunnelChart/curves/funnelStep.d.ts +0 -25
  152. package/FunnelChart/curves/funnelStep.js +0 -87
  153. package/esm/FunnelChart/curves/funnelStep.d.ts +0 -25
  154. package/esm/FunnelChart/curves/funnelStep.js +0 -80
@@ -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
  }));
@@ -46,7 +46,6 @@ const useAggregatedData = gap => {
46
46
  const bandWidth = (isXAxisBand || isYAxisBand) && baseScaleConfig.scale?.bandwidth() || 0;
47
47
  const xScale = xAxis[xAxisId].scale;
48
48
  const yScale = yAxis[yAxisId].scale;
49
- const curve = getFunnelCurve(currentSeries.curve, isHorizontal, gap);
50
49
  const xPosition = (value, bandIndex, stackOffset, useBand) => {
51
50
  if (isXAxisBand) {
52
51
  const position = xScale(bandIndex);
@@ -61,7 +60,17 @@ const useAggregatedData = gap => {
61
60
  }
62
61
  return yScale(isHorizontal ? value : value + (stackOffset || 0));
63
62
  };
64
- 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) => {
65
74
  const color = currentSeries.data[dataIndex].color;
66
75
  const id = `${seriesId}-${dataIndex}`;
67
76
  const sectionLabel = typeof currentSeries.sectionLabel === 'function' ? currentSeries.sectionLabel({
@@ -69,6 +78,15 @@ const useAggregatedData = gap => {
69
78
  seriesId,
70
79
  value: currentSeries.data[dataIndex].value
71
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
+ });
72
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);
73
91
  return {
74
92
  d: line(values),
@@ -76,6 +94,7 @@ const useAggregatedData = gap => {
76
94
  id,
77
95
  seriesId,
78
96
  dataIndex,
97
+ variant: currentSeries.variant,
79
98
  label: sectionLabel !== false && _extends({}, positionLabel(_extends({}, sectionLabel, {
80
99
  xPosition,
81
100
  yPosition,
@@ -109,13 +128,15 @@ function FunnelPlot(props) {
109
128
  color,
110
129
  id,
111
130
  seriesId,
112
- dataIndex
131
+ dataIndex,
132
+ variant
113
133
  }) => /*#__PURE__*/_createElement(FunnelSection, _extends({}, other, {
114
134
  d: d,
115
135
  color: color,
116
136
  key: id,
117
137
  dataIndex: dataIndex,
118
138
  seriesId: seriesId,
139
+ variant: variant,
119
140
  onClick: onItemClick && (event => {
120
141
  onItemClick(event, {
121
142
  type: 'funnel',
@@ -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
+ }
@@ -1,21 +1,24 @@
1
1
  import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
+ import { CurveOptions } from "./curve.types.js";
2
3
  /**
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.
4
7
  *
5
- * It takes into account the gap between the points and draws a smooth curve between them.
6
- *
7
- * It is based on the d3-shape bump curve generator.
8
+ * The implementation is based on the d3-shape bump curve generator.
8
9
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/bump.js
9
10
  */
10
11
  export declare class Bump implements CurveGenerator {
11
12
  private context;
12
- private line;
13
13
  private x;
14
14
  private y;
15
15
  private currentPoint;
16
16
  private isHorizontal;
17
17
  private gap;
18
- constructor(context: CanvasRenderingContext2D, isHorizontal: boolean, gap?: number);
18
+ constructor(context: CanvasRenderingContext2D, {
19
+ isHorizontal,
20
+ gap
21
+ }: CurveOptions);
19
22
  areaStart(): void;
20
23
  areaEnd(): void;
21
24
  lineStart(): void;
@@ -1,39 +1,32 @@
1
+ /* eslint-disable class-methods-use-this */
2
+
1
3
  /**
2
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.
3
7
  *
4
- * It takes into account the gap between the points and draws a smooth curve between them.
5
- *
6
- * It is based on the d3-shape bump curve generator.
8
+ * The implementation is based on the d3-shape bump curve generator.
7
9
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/bump.js
8
10
  */
9
11
  export class Bump {
10
- constructor(context, isHorizontal, gap = 0) {
12
+ constructor(context, {
13
+ isHorizontal,
14
+ gap
15
+ }) {
11
16
  this.context = void 0;
12
- this.line = NaN;
13
17
  this.x = NaN;
14
18
  this.y = NaN;
15
19
  this.currentPoint = 0;
16
20
  this.isHorizontal = false;
17
21
  this.gap = 0;
18
22
  this.context = context;
19
- this.isHorizontal = isHorizontal;
20
- this.gap = gap / 2;
21
- }
22
- areaStart() {
23
- this.line = 0;
24
- }
25
- areaEnd() {
26
- this.line = NaN;
27
- }
28
- lineStart() {
29
- this.currentPoint = 0;
30
- }
31
- lineEnd() {
32
- if (this.line || this.line !== 0 && this.currentPoint === 1) {
33
- this.context.closePath();
34
- }
35
- this.line = 1 - this.line;
23
+ this.isHorizontal = isHorizontal ?? false;
24
+ this.gap = (gap ?? 0) / 2;
36
25
  }
26
+ areaStart() {}
27
+ areaEnd() {}
28
+ lineStart() {}
29
+ lineEnd() {}
37
30
  point(x, y) {
38
31
  x = +x;
39
32
  y = +y;
@@ -50,6 +43,9 @@ export class Bump {
50
43
  } else {
51
44
  this.context.bezierCurveTo((this.x + x) / 2, this.y, (this.x + x) / 2, y, x + this.gap, y);
52
45
  }
46
+ if (this.currentPoint === 3) {
47
+ this.context.closePath();
48
+ }
53
49
  this.currentPoint += 1;
54
50
  this.x = x;
55
51
  this.y = y;
@@ -68,6 +64,9 @@ export class Bump {
68
64
  } else {
69
65
  this.context.bezierCurveTo(this.x, (this.y + y) / 2, x, (this.y + y) / 2, x, y + this.gap);
70
66
  }
67
+ if (this.currentPoint === 3) {
68
+ this.context.closePath();
69
+ }
71
70
  this.currentPoint += 1;
72
71
  this.x = x;
73
72
  this.y = y;
@@ -1,8 +1,38 @@
1
- export type FunnelCurveOptions = {
1
+ export type CurveOptions = {
2
2
  /**
3
- * The gap between the funnel segments.
3
+ * The gap between each segment.
4
4
  * @default 0
5
5
  */
6
6
  gap?: number;
7
+ /**
8
+ * Indicates if the main axis of the visualization.
9
+ */
10
+ isHorizontal?: boolean;
11
+ /**
12
+ * The order position of the segment.
13
+ */
14
+ position?: number;
15
+ /**
16
+ * The total number of segments that will be drawn.
17
+ * @default 1
18
+ */
19
+ sections?: number;
20
+ /**
21
+ * The border radius of the segments.
22
+ * @default 0
23
+ */
24
+ borderRadius?: number;
25
+ /**
26
+ * The minimum point for all the segments.
27
+ */
28
+ min?: Point;
29
+ /**
30
+ * The maximum point for all the segments.
31
+ */
32
+ max?: Point;
7
33
  };
8
- export type FunnelCurveType = 'linear' | 'step' | 'bump';
34
+ export type FunnelCurveType = 'linear' | 'step' | 'bump' | 'pyramid' | 'step-pyramid';
35
+ export type Point = {
36
+ x: number;
37
+ y: number;
38
+ };
@@ -1,3 +1,3 @@
1
1
  import { CurveFactory } from '@mui/x-charts-vendor/d3-shape';
2
- import { FunnelCurveType } from "./curve.types.js";
3
- export declare const getFunnelCurve: (curve: FunnelCurveType | undefined, isHorizontal: boolean, gap?: number) => CurveFactory;
2
+ import { CurveOptions, FunnelCurveType } from "./curve.types.js";
3
+ export declare const getFunnelCurve: (curve: FunnelCurveType | undefined, options: CurveOptions) => CurveFactory;
@@ -1,15 +1,23 @@
1
- import { FunnelStep } from "./funnelStep.js";
1
+ import { Step } from "./step.js";
2
2
  import { Linear } from "./linear.js";
3
3
  import { Bump } from "./bump.js";
4
+ import { Pyramid } from "./pyramid.js";
5
+ import { StepPyramid } from "./step-pyramid.js";
4
6
  const curveConstructor = curve => {
5
7
  if (curve === 'step') {
6
- return FunnelStep;
8
+ return Step;
7
9
  }
8
10
  if (curve === 'bump') {
9
11
  return Bump;
10
12
  }
13
+ if (curve === 'pyramid') {
14
+ return Pyramid;
15
+ }
16
+ if (curve === 'step-pyramid') {
17
+ return StepPyramid;
18
+ }
11
19
  return Linear;
12
20
  };
13
- export const getFunnelCurve = (curve, isHorizontal, gap = 0) => {
14
- return context => new (curveConstructor(curve))(context, isHorizontal, gap);
21
+ export const getFunnelCurve = (curve, options) => {
22
+ return context => new (curveConstructor(curve))(context, options);
15
23
  };
@@ -1,24 +1,32 @@
1
1
  import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
+ import { CurveOptions } from "./curve.types.js";
2
3
  /**
3
4
  * This is a custom "linear" curve generator.
5
+ * It draws straight lines for the 4 provided points,
6
+ * with the option to add a gap between sections while also properly handling the border radius.
4
7
  *
5
- * It takes into account the gap between the points and draws a smooth curve between them.
6
- *
7
- * It is based on the d3-shape linear curve generator.
8
+ * The implementation is based on the d3-shape linear curve generator.
8
9
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/linear.js
9
10
  */
10
11
  export declare class Linear implements CurveGenerator {
11
12
  private context;
12
- private line;
13
- private x;
14
- private y;
15
- private currentPoint;
13
+ private position;
14
+ private sections;
16
15
  private isHorizontal;
17
16
  private gap;
18
- constructor(context: CanvasRenderingContext2D, isHorizontal: boolean, gap?: number);
17
+ private borderRadius;
18
+ private points;
19
+ constructor(context: CanvasRenderingContext2D, {
20
+ isHorizontal,
21
+ gap,
22
+ position,
23
+ sections,
24
+ borderRadius
25
+ }: CurveOptions);
19
26
  areaStart(): void;
20
27
  areaEnd(): void;
21
28
  lineStart(): void;
22
29
  lineEnd(): void;
23
- point(x: number, y: number): void;
30
+ protected getBorderRadius(): number | number[];
31
+ point(xIn: number, yIn: number): void;
24
32
  }
@@ -1,106 +1,82 @@
1
- // From point1 to point2, get the x value from y
2
- const xFromY = (x1, y1, x2, y2) => y => {
3
- if (y1 === y2) {
4
- return x1;
5
- }
6
- const result = (x2 - x1) * (y - y1) / (y2 - y1) + x1;
7
- return Number.isNaN(result) ? 0 : result;
8
- };
1
+ /* eslint-disable class-methods-use-this */
9
2
 
10
- // From point1 to point2, get the y value from x
11
- const yFromX = (x1, y1, x2, y2) => x => {
12
- if (x1 === x2) {
13
- return y1;
14
- }
15
- const result = (y2 - y1) * (x - x1) / (x2 - x1) + y1;
16
- return Number.isNaN(result) ? 0 : result;
17
- };
3
+ import { borderRadiusPolygon } from "./borderRadiusPolygon.js";
4
+ import { lerpX, lerpY } from "./utils.js";
18
5
 
19
6
  /**
20
7
  * This is a custom "linear" curve generator.
8
+ * It draws straight lines for the 4 provided points,
9
+ * with the option to add a gap between sections while also properly handling the border radius.
21
10
  *
22
- * It takes into account the gap between the points and draws a smooth curve between them.
23
- *
24
- * It is based on the d3-shape linear curve generator.
11
+ * The implementation is based on the d3-shape linear curve generator.
25
12
  * https://github.com/d3/d3-shape/blob/a82254af78f08799c71d7ab25df557c4872a3c51/src/curve/linear.js
26
13
  */
27
14
  export class Linear {
28
- constructor(context, isHorizontal, gap = 0) {
15
+ constructor(context, {
16
+ isHorizontal,
17
+ gap,
18
+ position,
19
+ sections,
20
+ borderRadius
21
+ }) {
29
22
  this.context = void 0;
30
- this.line = NaN;
31
- this.x = NaN;
32
- this.y = NaN;
33
- this.currentPoint = 0;
23
+ this.position = 0;
24
+ this.sections = 0;
34
25
  this.isHorizontal = false;
35
26
  this.gap = 0;
27
+ this.borderRadius = 0;
28
+ this.points = [];
36
29
  this.context = context;
37
- this.isHorizontal = isHorizontal;
38
- this.gap = gap / 2;
39
- }
40
- areaStart() {
41
- this.line = 0;
30
+ this.isHorizontal = isHorizontal ?? false;
31
+ this.gap = (gap ?? 0) / 2;
32
+ this.position = position ?? 0;
33
+ this.sections = sections ?? 1;
34
+ this.borderRadius = borderRadius ?? 0;
42
35
  }
43
- areaEnd() {
44
- this.line = NaN;
45
- }
46
- lineStart() {
47
- this.currentPoint = 0;
48
- }
49
- lineEnd() {
50
- if (this.line || this.line !== 0 && this.currentPoint === 1) {
51
- this.context.closePath();
36
+ areaStart() {}
37
+ areaEnd() {}
38
+ lineStart() {}
39
+ lineEnd() {}
40
+ getBorderRadius() {
41
+ if (this.gap > 0) {
42
+ return this.borderRadius;
43
+ }
44
+ if (this.position === 0) {
45
+ return [0, 0, this.borderRadius, this.borderRadius];
52
46
  }
53
- this.line = 1 - this.line;
47
+ if (this.position === this.sections - 1) {
48
+ return [this.borderRadius, this.borderRadius];
49
+ }
50
+ return 0;
54
51
  }
55
- point(x, y) {
56
- x = +x;
57
- y = +y;
58
-
59
- // We draw the lines only at currentPoint 1 & 3 because we need
60
- // The data of a pair of points to draw the lines.
61
- // Hence currentPoint 1 draws a line from point 0 to point 1 and point 1 to point 2.
62
- // currentPoint 3 draws a line from point 2 to point 3 and point 3 to point 0.
63
-
64
- if (this.isHorizontal) {
65
- const yGetter = yFromX(this.x, this.y, x, y);
66
- let xGap = 0;
67
-
68
- // 0 is the top-left corner.
69
- if (this.currentPoint === 1) {
70
- xGap = this.x + this.gap;
71
- this.context.moveTo(xGap, yGetter(xGap));
72
- this.context.lineTo(xGap, yGetter(xGap));
73
- xGap = x - this.gap;
74
- this.context.lineTo(xGap, yGetter(xGap));
75
- } else if (this.currentPoint === 3) {
76
- xGap = this.x - this.gap;
77
- this.context.lineTo(xGap, yGetter(xGap));
78
- xGap = x + this.gap;
79
- this.context.lineTo(xGap, yGetter(xGap));
80
- }
52
+ point(xIn, yIn) {
53
+ this.points.push({
54
+ x: xIn,
55
+ y: yIn
56
+ });
57
+ if (this.points.length < 4) {
58
+ return;
81
59
  }
82
- if (!this.isHorizontal) {
83
- const xGetter = xFromY(this.x, this.y, x, y);
84
- let yGap = 0;
85
60
 
86
- // 0 is the top-right corner.
87
- if (this.currentPoint === 1) {
88
- yGap = this.y + this.gap;
89
- this.context.moveTo(xGetter(yGap), yGap);
90
- this.context.lineTo(xGetter(yGap), yGap);
91
- yGap = y - this.gap;
92
- this.context.lineTo(xGetter(yGap), yGap);
93
- } else if (this.currentPoint === 3) {
94
- yGap = this.y - this.gap;
95
- this.context.lineTo(xGetter(yGap), yGap);
96
- yGap = y + this.gap;
97
- this.context.lineTo(xGetter(yGap), yGap);
61
+ // Add gaps where they are needed.
62
+ this.points = this.points.map((point, index) => {
63
+ const slopeStart = this.points.at(index <= 1 ? 0 : 2);
64
+ const slopeEnd = this.points.at(index <= 1 ? 1 : 3);
65
+ if (this.isHorizontal) {
66
+ const yGetter = lerpY(slopeStart.x - this.gap, slopeStart.y, slopeEnd.x - this.gap, slopeEnd.y);
67
+ const xGap = point.x + (index === 0 || index === 3 ? this.gap : -this.gap);
68
+ return {
69
+ x: xGap,
70
+ y: yGetter(xGap)
71
+ };
98
72
  }
99
- }
100
-
101
- // Increment the values
102
- this.currentPoint += 1;
103
- this.x = x;
104
- this.y = y;
73
+ const xGetter = lerpX(slopeStart.x, slopeStart.y - this.gap, slopeEnd.x, slopeEnd.y - this.gap);
74
+ const yGap = point.y + (index === 0 || index === 3 ? this.gap : -this.gap);
75
+ return {
76
+ x: xGetter(yGap),
77
+ y: yGap
78
+ };
79
+ });
80
+ borderRadiusPolygon(this.context, this.points, this.getBorderRadius());
105
81
  }
106
82
  }
@@ -0,0 +1,34 @@
1
+ import { CurveGenerator } from '@mui/x-charts-vendor/d3-shape';
2
+ import { CurveOptions } from "./curve.types.js";
3
+ /**
4
+ * This is a custom "pyramid" curve generator.
5
+ * It draws straight lines for the 4 provided points. The slopes are calculated
6
+ * based on the min and max values of the x and y axes.
7
+ * with the option to add a gap between sections while also properly handling the border radius.
8
+ */
9
+ export declare class Pyramid implements CurveGenerator {
10
+ private context;
11
+ private position;
12
+ private sections;
13
+ private isHorizontal;
14
+ private gap;
15
+ private borderRadius;
16
+ private min;
17
+ private max;
18
+ private points;
19
+ constructor(context: CanvasRenderingContext2D, {
20
+ isHorizontal,
21
+ gap,
22
+ position,
23
+ sections,
24
+ borderRadius,
25
+ min,
26
+ max
27
+ }: CurveOptions);
28
+ areaStart(): void;
29
+ areaEnd(): void;
30
+ lineStart(): void;
31
+ lineEnd(): void;
32
+ protected getBorderRadius(): number | number[];
33
+ point(xIn: number, yIn: number): void;
34
+ }