@mui/x-charts 9.2.0 → 9.4.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 (228) hide show
  1. package/BarChart/BarChart.js +10 -10
  2. package/BarChart/BarChart.mjs +10 -10
  3. package/BarChart/BarElement.d.mts +3 -2
  4. package/BarChart/BarElement.d.ts +3 -2
  5. package/BarChart/BarLabel/BarLabelItem.d.mts +3 -2
  6. package/BarChart/BarLabel/BarLabelItem.d.ts +3 -2
  7. package/BarChart/seriesConfig/bar/extremums.js +7 -2
  8. package/BarChart/seriesConfig/bar/extremums.mjs +7 -2
  9. package/BarChart/seriesConfig/bar/getColor.js +7 -53
  10. package/BarChart/seriesConfig/bar/getColor.mjs +7 -53
  11. package/BarChart/seriesConfig/bar/seriesProcessor.js +3 -1
  12. package/BarChart/seriesConfig/bar/seriesProcessor.mjs +3 -1
  13. package/BarChart/seriesConfig/bar/tooltip.js +4 -27
  14. package/BarChart/seriesConfig/bar/tooltip.mjs +4 -27
  15. package/CHANGELOG.md +314 -0
  16. package/ChartsContainer/ChartsContainer.js +30 -9
  17. package/ChartsContainer/ChartsContainer.mjs +30 -9
  18. package/ChartsLabel/ChartsLabelMark.js +1 -23
  19. package/ChartsLabel/ChartsLabelMark.mjs +0 -22
  20. package/ChartsLabel/labelMarkClasses.d.mts +0 -1
  21. package/ChartsLabel/labelMarkClasses.d.ts +0 -1
  22. package/ChartsLabel/labelMarkClasses.js +1 -2
  23. package/ChartsLabel/labelMarkClasses.mjs +2 -2
  24. package/ChartsLayerContainer/ChartsLayerContainer.js +36 -30
  25. package/ChartsLayerContainer/ChartsLayerContainer.mjs +36 -30
  26. package/ChartsLegend/chartsLegend.types.d.mts +3 -2
  27. package/ChartsLegend/chartsLegend.types.d.ts +3 -2
  28. package/ChartsLegend/piecewiseColorLegendClasses.js +8 -2
  29. package/ChartsLegend/piecewiseColorLegendClasses.mjs +8 -2
  30. package/ChartsOverlay/ChartsOverlay.d.mts +5 -4
  31. package/ChartsOverlay/ChartsOverlay.d.ts +5 -4
  32. package/ChartsReferenceLine/ChartsXReferenceLine.js +6 -1
  33. package/ChartsReferenceLine/ChartsXReferenceLine.mjs +6 -1
  34. package/ChartsReferenceLine/ChartsYReferenceLine.js +5 -0
  35. package/ChartsReferenceLine/ChartsYReferenceLine.mjs +5 -0
  36. package/ChartsTooltip/ChartTooltip.types.d.mts +3 -2
  37. package/ChartsTooltip/ChartTooltip.types.d.ts +3 -2
  38. package/ChartsTooltip/useAxesTooltip.js +2 -2
  39. package/ChartsTooltip/useAxesTooltip.mjs +2 -2
  40. package/ChartsTooltip/useItemTooltip.js +2 -2
  41. package/ChartsTooltip/useItemTooltip.mjs +2 -2
  42. package/ChartsXAxis/ChartsXAxis.js +3 -1
  43. package/ChartsXAxis/ChartsXAxis.mjs +3 -1
  44. package/ChartsXAxis/useAxisTicksProps.d.mts +84 -3
  45. package/ChartsXAxis/useAxisTicksProps.d.ts +84 -3
  46. package/ChartsYAxis/ChartsYAxis.js +3 -1
  47. package/ChartsYAxis/ChartsYAxis.mjs +3 -1
  48. package/ChartsYAxis/useAxisTicksProps.d.mts +84 -3
  49. package/ChartsYAxis/useAxisTicksProps.d.ts +84 -3
  50. package/LineChart/AreaElement.d.mts +3 -2
  51. package/LineChart/AreaElement.d.ts +3 -2
  52. package/LineChart/LineChart.js +6 -6
  53. package/LineChart/LineChart.mjs +6 -6
  54. package/LineChart/LineElement.d.mts +3 -2
  55. package/LineChart/LineElement.d.ts +3 -2
  56. package/LineChart/LineHighlightPlot.d.mts +3 -2
  57. package/LineChart/LineHighlightPlot.d.ts +3 -2
  58. package/LineChart/LineHighlightPlot.js +65 -45
  59. package/LineChart/LineHighlightPlot.mjs +65 -45
  60. package/LineChart/MarkPlot.d.mts +3 -2
  61. package/LineChart/MarkPlot.d.ts +3 -2
  62. package/LineChart/seriesConfig/curveEvaluation.js +40 -15
  63. package/LineChart/seriesConfig/curveEvaluation.mjs +39 -15
  64. package/LineChart/seriesConfig/extremums.js +5 -1
  65. package/LineChart/seriesConfig/extremums.mjs +5 -1
  66. package/LineChart/seriesConfig/getColor.js +7 -54
  67. package/LineChart/seriesConfig/getColor.mjs +7 -54
  68. package/LineChart/seriesConfig/seriesProcessor.d.mts +2 -4
  69. package/LineChart/seriesConfig/seriesProcessor.d.ts +2 -4
  70. package/LineChart/seriesConfig/seriesProcessor.js +2 -139
  71. package/LineChart/seriesConfig/seriesProcessor.mjs +2 -138
  72. package/LineChart/seriesConfig/tooltip.js +4 -25
  73. package/LineChart/seriesConfig/tooltip.mjs +4 -25
  74. package/LineChart/useMarkPlotData.js +3 -1
  75. package/LineChart/useMarkPlotData.mjs +3 -1
  76. package/PieChart/PieArcLabelPlot.d.mts +3 -2
  77. package/PieChart/PieArcLabelPlot.d.ts +3 -2
  78. package/PieChart/PieArcPlot.d.mts +3 -2
  79. package/PieChart/PieArcPlot.d.ts +3 -2
  80. package/PieChart/PieChart.js +6 -6
  81. package/PieChart/PieChart.mjs +6 -6
  82. package/RadarChart/RadarAxis/RadarAxis.utils.d.mts +2 -2
  83. package/RadarChart/RadarAxis/RadarAxis.utils.d.ts +2 -2
  84. package/RadarChart/RadarAxis/useRadarAxis.js +1 -1
  85. package/RadarChart/RadarAxis/useRadarAxis.mjs +1 -1
  86. package/RadarChart/RadarChart.js +8 -8
  87. package/RadarChart/RadarChart.mjs +8 -8
  88. package/RadarChart/RadarSeriesPlot/RadarSeriesArea.js +3 -1
  89. package/RadarChart/RadarSeriesPlot/RadarSeriesArea.mjs +3 -1
  90. package/RadarChart/RadarSeriesPlot/RadarSeriesMarks.js +1 -0
  91. package/RadarChart/RadarSeriesPlot/RadarSeriesMarks.mjs +1 -0
  92. package/RadarChart/RadarSeriesPlot/RadarSeriesPlot.js +1 -0
  93. package/RadarChart/RadarSeriesPlot/RadarSeriesPlot.mjs +1 -0
  94. package/ScatterChart/BatchScatter.d.mts +2 -8
  95. package/ScatterChart/BatchScatter.d.ts +2 -8
  96. package/ScatterChart/BatchScatter.js +17 -12
  97. package/ScatterChart/BatchScatter.mjs +17 -12
  98. package/ScatterChart/FocusedScatterMark.js +2 -2
  99. package/ScatterChart/FocusedScatterMark.mjs +2 -2
  100. package/ScatterChart/HighlightedScatterMark.js +3 -3
  101. package/ScatterChart/HighlightedScatterMark.mjs +3 -3
  102. package/ScatterChart/Scatter.d.mts +5 -0
  103. package/ScatterChart/Scatter.d.ts +5 -0
  104. package/ScatterChart/Scatter.js +7 -2
  105. package/ScatterChart/Scatter.mjs +7 -2
  106. package/ScatterChart/ScatterChart.d.mts +2 -1
  107. package/ScatterChart/ScatterChart.d.ts +2 -1
  108. package/ScatterChart/ScatterChart.js +32 -11
  109. package/ScatterChart/ScatterChart.mjs +32 -11
  110. package/ScatterChart/ScatterMarker.types.d.mts +3 -2
  111. package/ScatterChart/ScatterMarker.types.d.ts +3 -2
  112. package/ScatterChart/ScatterPlot.d.mts +3 -2
  113. package/ScatterChart/ScatterPlot.d.ts +3 -2
  114. package/ScatterChart/ScatterPlot.js +6 -1
  115. package/ScatterChart/ScatterPlot.mjs +6 -1
  116. package/ScatterChart/seriesConfig/extremums.js +6 -0
  117. package/ScatterChart/seriesConfig/extremums.mjs +6 -0
  118. package/ScatterChart/seriesConfig/getColor.js +1 -1
  119. package/ScatterChart/seriesConfig/getColor.mjs +1 -1
  120. package/ScatterChart/seriesConfig/getMarkerSize.d.mts +18 -0
  121. package/ScatterChart/seriesConfig/getMarkerSize.d.ts +18 -0
  122. package/ScatterChart/seriesConfig/getMarkerSize.js +43 -0
  123. package/ScatterChart/seriesConfig/getMarkerSize.mjs +37 -0
  124. package/ScatterChart/seriesConfig/seriesProcessor.js +23 -8
  125. package/ScatterChart/seriesConfig/seriesProcessor.mjs +23 -8
  126. package/ScatterChart/seriesConfig/tooltip.js +2 -24
  127. package/ScatterChart/seriesConfig/tooltip.mjs +2 -24
  128. package/ScatterChart/useScatterItemPosition.d.mts +4 -0
  129. package/ScatterChart/useScatterItemPosition.d.ts +4 -0
  130. package/ScatterChart/useScatterItemPosition.js +9 -0
  131. package/ScatterChart/useScatterItemPosition.mjs +8 -0
  132. package/SparkLineChart/SparkLineChart.js +27 -27
  133. package/SparkLineChart/SparkLineChart.mjs +27 -27
  134. package/Toolbar/Toolbar.types.d.mts +3 -2
  135. package/Toolbar/Toolbar.types.d.ts +3 -2
  136. package/index.js +1 -1
  137. package/index.mjs +1 -1
  138. package/internals/animation/animation.d.mts +1 -2
  139. package/internals/animation/animation.d.ts +1 -2
  140. package/internals/commonNextFocusItem.d.mts +10 -2
  141. package/internals/commonNextFocusItem.d.ts +10 -2
  142. package/internals/commonNextFocusItem.js +12 -4
  143. package/internals/commonNextFocusItem.mjs +12 -4
  144. package/internals/components/ChartsAccessibilityProxy/ChartsAccessibilityProxy.js +1 -1
  145. package/internals/components/ChartsAccessibilityProxy/ChartsAccessibilityProxy.mjs +1 -1
  146. package/internals/createCommonKeyboardFocusHandler.d.mts +1 -1
  147. package/internals/createCommonKeyboardFocusHandler.d.ts +1 -1
  148. package/internals/createCommonKeyboardFocusHandler.js +3 -3
  149. package/internals/createCommonKeyboardFocusHandler.mjs +3 -3
  150. package/internals/getLineLikeTooltip.d.mts +9 -0
  151. package/internals/getLineLikeTooltip.d.ts +9 -0
  152. package/internals/getLineLikeTooltip.js +38 -0
  153. package/internals/getLineLikeTooltip.mjs +31 -0
  154. package/internals/incompleteDatasetKeysError.d.mts +1 -0
  155. package/internals/incompleteDatasetKeysError.d.ts +1 -0
  156. package/internals/incompleteDatasetKeysError.js +11 -0
  157. package/internals/incompleteDatasetKeysError.mjs +4 -0
  158. package/internals/index.d.mts +5 -0
  159. package/internals/index.d.ts +5 -0
  160. package/internals/index.js +48 -0
  161. package/internals/index.mjs +5 -0
  162. package/internals/plugins/corePlugins/useChartSeriesConfig/types/tooltipGetter.types.d.mts +4 -2
  163. package/internals/plugins/corePlugins/useChartSeriesConfig/types/tooltipGetter.types.d.ts +4 -2
  164. package/internals/plugins/featurePlugins/useChartCartesianAxis/createZoomLookup.js +3 -2
  165. package/internals/plugins/featurePlugins/useChartCartesianAxis/createZoomLookup.mjs +4 -3
  166. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.js +2 -2
  167. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.mjs +3 -3
  168. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.d.mts +10 -1
  169. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.d.ts +10 -1
  170. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.js +18 -1
  171. package/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeZoom.mjs +16 -0
  172. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.mts +11 -3
  173. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.d.ts +11 -3
  174. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.js +24 -5
  175. package/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxisRendering.selectors.mjs +24 -5
  176. package/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.d.mts +1 -1
  177. package/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.d.ts +1 -1
  178. package/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.js +46 -2
  179. package/internals/plugins/featurePlugins/useChartClosestPoint/findClosestPoints.mjs +47 -2
  180. package/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.js +46 -11
  181. package/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.mjs +46 -11
  182. package/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.types.d.mts +2 -1
  183. package/internals/plugins/featurePlugins/useChartClosestPoint/useChartClosestPoint.types.d.ts +2 -1
  184. package/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.js +6 -2
  185. package/internals/plugins/featurePlugins/useChartHighlight/useChartHighlight.mjs +6 -2
  186. package/internals/plugins/featurePlugins/useChartPolarAxis/coordinateTransformation.d.mts +4 -0
  187. package/internals/plugins/featurePlugins/useChartPolarAxis/coordinateTransformation.d.ts +4 -0
  188. package/internals/plugins/featurePlugins/useChartPolarAxis/coordinateTransformation.js +3 -1
  189. package/internals/plugins/featurePlugins/useChartPolarAxis/coordinateTransformation.mjs +1 -0
  190. package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.js +5 -3
  191. package/internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarAxis.mjs +7 -5
  192. package/internals/plugins/featurePlugins/useChartZAxis/useChartZAxis.js +17 -3
  193. package/internals/plugins/featurePlugins/useChartZAxis/useChartZAxis.mjs +17 -3
  194. package/internals/processLineLikeSeries.d.mts +6 -0
  195. package/internals/processLineLikeSeries.d.ts +6 -0
  196. package/internals/processLineLikeSeries.js +145 -0
  197. package/internals/processLineLikeSeries.mjs +138 -0
  198. package/internals/resolveColorProcessor.d.mts +11 -0
  199. package/internals/resolveColorProcessor.d.ts +11 -0
  200. package/internals/resolveColorProcessor.js +62 -0
  201. package/internals/resolveColorProcessor.mjs +56 -0
  202. package/internals/sizeScale.d.mts +6 -0
  203. package/internals/sizeScale.d.ts +6 -0
  204. package/internals/sizeScale.js +46 -0
  205. package/internals/sizeScale.mjs +38 -0
  206. package/models/axis.d.mts +18 -12
  207. package/models/axis.d.ts +18 -12
  208. package/models/chartsSlotsComponentsProps.d.mts +25 -0
  209. package/models/chartsSlotsComponentsProps.d.ts +25 -0
  210. package/models/chartsSlotsComponentsProps.js +5 -0
  211. package/models/chartsSlotsComponentsProps.mjs +1 -0
  212. package/models/index.d.mts +1 -0
  213. package/models/index.d.ts +1 -0
  214. package/models/index.js +11 -0
  215. package/models/index.mjs +1 -0
  216. package/models/seriesType/line.d.mts +5 -2
  217. package/models/seriesType/line.d.ts +5 -2
  218. package/models/seriesType/scatter.d.mts +34 -2
  219. package/models/seriesType/scatter.d.ts +34 -2
  220. package/models/sizeMapping.d.mts +64 -0
  221. package/models/sizeMapping.d.ts +64 -0
  222. package/models/sizeMapping.js +5 -0
  223. package/models/sizeMapping.mjs +1 -0
  224. package/models/slots/chartsBaseSlots.d.mts +6 -5
  225. package/models/slots/chartsBaseSlots.d.ts +6 -5
  226. package/models/z-axis.d.mts +10 -1
  227. package/models/z-axis.d.ts +10 -1
  228. package/package.json +6 -6
@@ -3,6 +3,7 @@ import { type SlotComponentPropsFromProps } from '@mui/x-internals/types';
3
3
  import { type AnimatedAreaProps } from "./AnimatedArea.js";
4
4
  import { type SeriesId } from "../models/seriesType/common.js";
5
5
  import { type LineClasses } from "./lineClasses.js";
6
+ import type { AreaPropsOverrides } from "../models/chartsSlotsComponentsProps.js";
6
7
  export interface AreaElementOwnerState {
7
8
  seriesId: SeriesId;
8
9
  color: string;
@@ -16,10 +17,10 @@ export interface AreaElementSlots {
16
17
  * The component that renders the area.
17
18
  * @default AnimatedArea
18
19
  */
19
- area?: React.JSXElementConstructor<AnimatedAreaProps>;
20
+ area?: React.JSXElementConstructor<AnimatedAreaProps & AreaPropsOverrides>;
20
21
  }
21
22
  export interface AreaElementSlotProps {
22
- area?: SlotComponentPropsFromProps<AnimatedAreaProps, {}, AreaElementOwnerState>;
23
+ area?: SlotComponentPropsFromProps<AnimatedAreaProps, AreaPropsOverrides, AreaElementOwnerState>;
23
24
  }
24
25
  export interface AreaElementProps extends Omit<AreaElementOwnerState, 'isFaded' | 'isHighlighted'>, Pick<AnimatedAreaProps, 'skipAnimation'>, Omit<React.SVGProps<SVGPathElement>, 'ref' | 'color'> {
25
26
  d: string;
@@ -205,11 +205,11 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
205
205
  */
206
206
  highlightedItem: _propTypes.default.oneOfType([_propTypes.default.shape({
207
207
  dataIndex: _propTypes.default.number,
208
- seriesId: _propTypes.default.string.isRequired,
209
- type: _propTypes.default.oneOf(['line']).isRequired
208
+ seriesId: _propTypes.default.string.isRequired
210
209
  }), _propTypes.default.shape({
211
210
  dataIndex: _propTypes.default.number,
212
- seriesId: _propTypes.default.string.isRequired
211
+ seriesId: _propTypes.default.string.isRequired,
212
+ type: _propTypes.default.oneOf(['line']).isRequired
213
213
  })]),
214
214
  /**
215
215
  * This prop is used to help implement the accessibility logic.
@@ -365,11 +365,11 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
365
365
  */
366
366
  tooltipItem: _propTypes.default.oneOfType([_propTypes.default.shape({
367
367
  dataIndex: _propTypes.default.number,
368
- seriesId: _propTypes.default.string.isRequired,
369
- type: _propTypes.default.oneOf(['line']).isRequired
368
+ seriesId: _propTypes.default.string.isRequired
370
369
  }), _propTypes.default.shape({
371
370
  dataIndex: _propTypes.default.number,
372
- seriesId: _propTypes.default.string.isRequired
371
+ seriesId: _propTypes.default.string.isRequired,
372
+ type: _propTypes.default.oneOf(['line']).isRequired
373
373
  })]),
374
374
  /**
375
375
  * The width of the chart in px. If not defined, it takes the width of the parent element.
@@ -198,11 +198,11 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
198
198
  */
199
199
  highlightedItem: PropTypes.oneOfType([PropTypes.shape({
200
200
  dataIndex: PropTypes.number,
201
- seriesId: PropTypes.string.isRequired,
202
- type: PropTypes.oneOf(['line']).isRequired
201
+ seriesId: PropTypes.string.isRequired
203
202
  }), PropTypes.shape({
204
203
  dataIndex: PropTypes.number,
205
- seriesId: PropTypes.string.isRequired
204
+ seriesId: PropTypes.string.isRequired,
205
+ type: PropTypes.oneOf(['line']).isRequired
206
206
  })]),
207
207
  /**
208
208
  * This prop is used to help implement the accessibility logic.
@@ -358,11 +358,11 @@ process.env.NODE_ENV !== "production" ? LineChart.propTypes = {
358
358
  */
359
359
  tooltipItem: PropTypes.oneOfType([PropTypes.shape({
360
360
  dataIndex: PropTypes.number,
361
- seriesId: PropTypes.string.isRequired,
362
- type: PropTypes.oneOf(['line']).isRequired
361
+ seriesId: PropTypes.string.isRequired
363
362
  }), PropTypes.shape({
364
363
  dataIndex: PropTypes.number,
365
- seriesId: PropTypes.string.isRequired
364
+ seriesId: PropTypes.string.isRequired,
365
+ type: PropTypes.oneOf(['line']).isRequired
366
366
  })]),
367
367
  /**
368
368
  * The width of the chart in px. If not defined, it takes the width of the parent element.
@@ -3,6 +3,7 @@ import { type SlotComponentPropsFromProps } from '@mui/x-internals/types';
3
3
  import { type AnimatedLineProps } from "./AnimatedLine.mjs";
4
4
  import { type SeriesId } from "../models/seriesType/common.mjs";
5
5
  import { type LineClasses } from "./lineClasses.mjs";
6
+ import type { LinePropsOverrides } from "../models/chartsSlotsComponentsProps.mjs";
6
7
  export interface LineElementOwnerState {
7
8
  seriesId: SeriesId;
8
9
  color: string;
@@ -18,10 +19,10 @@ export interface LineElementSlots {
18
19
  * The component that renders the line.
19
20
  * @default LineElementPath
20
21
  */
21
- line?: React.JSXElementConstructor<AnimatedLineProps>;
22
+ line?: React.JSXElementConstructor<AnimatedLineProps & LinePropsOverrides>;
22
23
  }
23
24
  export interface LineElementSlotProps {
24
- line?: SlotComponentPropsFromProps<AnimatedLineProps, {}, LineElementOwnerState>;
25
+ line?: SlotComponentPropsFromProps<AnimatedLineProps, LinePropsOverrides, LineElementOwnerState>;
25
26
  }
26
27
  export interface LineElementProps extends Omit<LineElementOwnerState, 'isFaded' | 'isHighlighted'>, Pick<AnimatedLineProps, 'skipAnimation'>, Omit<React.SVGProps<SVGPathElement>, 'ref' | 'color'> {
27
28
  d: string;
@@ -3,6 +3,7 @@ import { type SlotComponentPropsFromProps } from '@mui/x-internals/types';
3
3
  import { type AnimatedLineProps } from "./AnimatedLine.js";
4
4
  import { type SeriesId } from "../models/seriesType/common.js";
5
5
  import { type LineClasses } from "./lineClasses.js";
6
+ import type { LinePropsOverrides } from "../models/chartsSlotsComponentsProps.js";
6
7
  export interface LineElementOwnerState {
7
8
  seriesId: SeriesId;
8
9
  color: string;
@@ -18,10 +19,10 @@ export interface LineElementSlots {
18
19
  * The component that renders the line.
19
20
  * @default LineElementPath
20
21
  */
21
- line?: React.JSXElementConstructor<AnimatedLineProps>;
22
+ line?: React.JSXElementConstructor<AnimatedLineProps & LinePropsOverrides>;
22
23
  }
23
24
  export interface LineElementSlotProps {
24
- line?: SlotComponentPropsFromProps<AnimatedLineProps, {}, LineElementOwnerState>;
25
+ line?: SlotComponentPropsFromProps<AnimatedLineProps, LinePropsOverrides, LineElementOwnerState>;
25
26
  }
26
27
  export interface LineElementProps extends Omit<LineElementOwnerState, 'isFaded' | 'isHighlighted'>, Pick<AnimatedLineProps, 'skipAnimation'>, Omit<React.SVGProps<SVGPathElement>, 'ref' | 'color'> {
27
28
  d: string;
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { type SlotComponentPropsFromProps } from '@mui/x-internals/types';
3
3
  import { type LineHighlightElementProps } from "./LineHighlightElement.mjs";
4
+ import type { LineHighlightPropsOverrides } from "../models/chartsSlotsComponentsProps.mjs";
4
5
  export interface LineHighlightPlotSlots {
5
- lineHighlight?: React.JSXElementConstructor<LineHighlightElementProps>;
6
+ lineHighlight?: React.JSXElementConstructor<LineHighlightElementProps & LineHighlightPropsOverrides>;
6
7
  }
7
8
  export interface LineHighlightPlotSlotProps {
8
- lineHighlight?: SlotComponentPropsFromProps<LineHighlightElementProps, {}, {}>;
9
+ lineHighlight?: SlotComponentPropsFromProps<LineHighlightElementProps, LineHighlightPropsOverrides, {}>;
9
10
  }
10
11
  export interface LineHighlightPlotProps extends React.SVGAttributes<SVGSVGElement> {
11
12
  /**
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { type SlotComponentPropsFromProps } from '@mui/x-internals/types';
3
3
  import { type LineHighlightElementProps } from "./LineHighlightElement.js";
4
+ import type { LineHighlightPropsOverrides } from "../models/chartsSlotsComponentsProps.js";
4
5
  export interface LineHighlightPlotSlots {
5
- lineHighlight?: React.JSXElementConstructor<LineHighlightElementProps>;
6
+ lineHighlight?: React.JSXElementConstructor<LineHighlightElementProps & LineHighlightPropsOverrides>;
6
7
  }
7
8
  export interface LineHighlightPlotSlotProps {
8
- lineHighlight?: SlotComponentPropsFromProps<LineHighlightElementProps, {}, {}>;
9
+ lineHighlight?: SlotComponentPropsFromProps<LineHighlightElementProps, LineHighlightPropsOverrides, {}>;
9
10
  }
10
11
  export interface LineHighlightPlotProps extends React.SVGAttributes<SVGSVGElement> {
11
12
  /**
@@ -53,9 +53,6 @@ function LineHighlightPlot(props) {
53
53
  } = (0, _ChartsProvider.useChartsContext)();
54
54
  const store = (0, _useStore.useStore)();
55
55
  const highlightedIndexes = store.use(_useChartCartesianAxis.selectorChartsHighlightXAxisIndex);
56
- if (highlightedIndexes.length === 0) {
57
- return null;
58
- }
59
56
  if (seriesData === undefined) {
60
57
  return null;
61
58
  }
@@ -65,54 +62,77 @@ function LineHighlightPlot(props) {
65
62
  } = seriesData;
66
63
  const defaultXAxisId = xAxisIds[0];
67
64
  const defaultYAxisId = yAxisIds[0];
65
+ const hasStartEndMark = stackingGroups.some(({
66
+ ids
67
+ }) => ids.some(seriesId => series[seriesId].showMark === 'start' || series[seriesId].showMark === 'end'));
68
+ if (highlightedIndexes.length === 0 && !hasStartEndMark) {
69
+ return null;
70
+ }
71
+ const getHighlightedIndex = new Map();
72
+ highlightedIndexes.forEach(({
73
+ axisId,
74
+ dataIndex
75
+ }) => {
76
+ getHighlightedIndex.set(axisId, dataIndex);
77
+ });
68
78
  const Element = slots?.lineHighlight ?? _LineHighlightElement.LineHighlightElement;
69
79
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("g", (0, _extends2.default)({}, other, {
70
- children: highlightedIndexes.flatMap(({
71
- dataIndex: highlightedIndex,
72
- axisId: highlightedAxisId
73
- }) => stackingGroups.flatMap(({
80
+ children: stackingGroups.flatMap(({
74
81
  ids: groupIds
75
- }) => {
76
- return groupIds.flatMap(seriesId => {
77
- const {
78
- xAxisId = defaultXAxisId,
79
- yAxisId = defaultYAxisId,
80
- visibleStackedData,
81
- data,
82
- disableHighlight,
83
- shape = 'circle',
84
- hidden
85
- } = series[seriesId];
86
- if (hidden || disableHighlight || data[highlightedIndex] == null) {
87
- return null;
88
- }
89
- if (highlightedAxisId !== xAxisId) {
90
- return null;
91
- }
92
- const xScale = (0, _getValueToPositionMapper.getValueToPositionMapper)(xAxis[xAxisId].scale);
93
- const yScale = yAxis[yAxisId].scale;
94
- const xData = xAxis[xAxisId].data;
95
- if (xData === undefined) {
96
- throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Charts: ${xAxisId === _constants.DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`} should have a data property to be able to display a line plot. ` + 'The x-axis data defines the positions for each point in the line. ' + 'Provide a data array to the x-axis configuration.' : (0, _formatErrorMessage2.default)(10, xAxisId === _constants.DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`));
97
- }
98
- const x = xScale(xData[highlightedIndex]);
99
- const y = yScale(visibleStackedData[highlightedIndex][1]); // This should not be undefined since y should not be a band scale
100
-
101
- if (!instance.isPointInside(x, y)) {
102
- return null;
103
- }
104
- const colorGetter = (0, _getColor.default)(series[seriesId], xAxis[xAxisId], yAxis[yAxisId]);
105
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Element, (0, _extends2.default)({
106
- seriesId: seriesId,
107
- color: colorGetter(highlightedIndex),
108
- x: x,
109
- y: y,
110
- shape: shape
111
- }, slotProps?.lineHighlight), `${seriesId}`);
112
- });
82
+ }) => groupIds.flatMap(seriesId => {
83
+ const {
84
+ xAxisId = defaultXAxisId,
85
+ yAxisId = defaultYAxisId,
86
+ visibleStackedData,
87
+ data,
88
+ disableHighlight,
89
+ showMark,
90
+ shape = 'circle',
91
+ hidden
92
+ } = series[seriesId];
93
+ if (hidden) {
94
+ return null;
95
+ }
96
+ const axisIndex = disableHighlight ? undefined : getHighlightedIndex.get(xAxisId);
97
+ const showMarkIndex = showMark === 'start' || showMark === 'end' ? getStartEndMarkIndex(data, showMark) : undefined;
98
+ const highlightedIndex = axisIndex ?? showMarkIndex;
99
+ if (highlightedIndex === undefined || data[highlightedIndex] == null) {
100
+ return null;
101
+ }
102
+ const xScale = (0, _getValueToPositionMapper.getValueToPositionMapper)(xAxis[xAxisId].scale);
103
+ const yScale = yAxis[yAxisId].scale;
104
+ const xData = xAxis[xAxisId].data;
105
+ if (xData === undefined) {
106
+ throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Charts: ${xAxisId === _constants.DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`} should have a data property to be able to display a line plot. ` + 'The x-axis data defines the positions for each point in the line. ' + 'Provide a data array to the x-axis configuration.' : (0, _formatErrorMessage2.default)(10, xAxisId === _constants.DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`));
107
+ }
108
+ const x = xScale(xData[highlightedIndex]);
109
+ const y = yScale(visibleStackedData[highlightedIndex][1]); // This should not be undefined since y should not be a band scale
110
+ if (!instance.isPointInside(x, y)) {
111
+ return null;
112
+ }
113
+ const colorGetter = (0, _getColor.default)(series[seriesId], xAxis[xAxisId], yAxis[yAxisId]);
114
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(Element, (0, _extends2.default)({
115
+ seriesId: seriesId,
116
+ color: colorGetter(highlightedIndex),
117
+ x: x,
118
+ y: y,
119
+ shape: shape
120
+ }, slotProps?.lineHighlight), `${seriesId}`);
113
121
  }))
114
122
  }));
115
123
  }
124
+
125
+ /**
126
+ * Returns the index of the first (`'start'`) or last (`'end'`) non-null item, or `-1` if none.
127
+ */
128
+ function getStartEndMarkIndex(data, type) {
129
+ if (type === 'start') {
130
+ const index = data.findIndex(value => value != null);
131
+ return index < 0 ? undefined : index;
132
+ }
133
+ const index = data.findLastIndex(value => value != null);
134
+ return index < 0 ? undefined : index;
135
+ }
116
136
  process.env.NODE_ENV !== "production" ? LineHighlightPlot.propTypes = {
117
137
  // ----------------------------- Warning --------------------------------
118
138
  // | These PropTypes are generated from the TypeScript type definitions |
@@ -46,9 +46,6 @@ function LineHighlightPlot(props) {
46
46
  } = useChartsContext();
47
47
  const store = useStore();
48
48
  const highlightedIndexes = store.use(selectorChartsHighlightXAxisIndex);
49
- if (highlightedIndexes.length === 0) {
50
- return null;
51
- }
52
49
  if (seriesData === undefined) {
53
50
  return null;
54
51
  }
@@ -58,54 +55,77 @@ function LineHighlightPlot(props) {
58
55
  } = seriesData;
59
56
  const defaultXAxisId = xAxisIds[0];
60
57
  const defaultYAxisId = yAxisIds[0];
58
+ const hasStartEndMark = stackingGroups.some(({
59
+ ids
60
+ }) => ids.some(seriesId => series[seriesId].showMark === 'start' || series[seriesId].showMark === 'end'));
61
+ if (highlightedIndexes.length === 0 && !hasStartEndMark) {
62
+ return null;
63
+ }
64
+ const getHighlightedIndex = new Map();
65
+ highlightedIndexes.forEach(({
66
+ axisId,
67
+ dataIndex
68
+ }) => {
69
+ getHighlightedIndex.set(axisId, dataIndex);
70
+ });
61
71
  const Element = slots?.lineHighlight ?? LineHighlightElement;
62
72
  return /*#__PURE__*/_jsx("g", _extends({}, other, {
63
- children: highlightedIndexes.flatMap(({
64
- dataIndex: highlightedIndex,
65
- axisId: highlightedAxisId
66
- }) => stackingGroups.flatMap(({
73
+ children: stackingGroups.flatMap(({
67
74
  ids: groupIds
68
- }) => {
69
- return groupIds.flatMap(seriesId => {
70
- const {
71
- xAxisId = defaultXAxisId,
72
- yAxisId = defaultYAxisId,
73
- visibleStackedData,
74
- data,
75
- disableHighlight,
76
- shape = 'circle',
77
- hidden
78
- } = series[seriesId];
79
- if (hidden || disableHighlight || data[highlightedIndex] == null) {
80
- return null;
81
- }
82
- if (highlightedAxisId !== xAxisId) {
83
- return null;
84
- }
85
- const xScale = getValueToPositionMapper(xAxis[xAxisId].scale);
86
- const yScale = yAxis[yAxisId].scale;
87
- const xData = xAxis[xAxisId].data;
88
- if (xData === undefined) {
89
- throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Charts: ${xAxisId === DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`} should have a data property to be able to display a line plot. ` + 'The x-axis data defines the positions for each point in the line. ' + 'Provide a data array to the x-axis configuration.' : _formatErrorMessage(10, xAxisId === DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`));
90
- }
91
- const x = xScale(xData[highlightedIndex]);
92
- const y = yScale(visibleStackedData[highlightedIndex][1]); // This should not be undefined since y should not be a band scale
93
-
94
- if (!instance.isPointInside(x, y)) {
95
- return null;
96
- }
97
- const colorGetter = getColor(series[seriesId], xAxis[xAxisId], yAxis[yAxisId]);
98
- return /*#__PURE__*/_jsx(Element, _extends({
99
- seriesId: seriesId,
100
- color: colorGetter(highlightedIndex),
101
- x: x,
102
- y: y,
103
- shape: shape
104
- }, slotProps?.lineHighlight), `${seriesId}`);
105
- });
75
+ }) => groupIds.flatMap(seriesId => {
76
+ const {
77
+ xAxisId = defaultXAxisId,
78
+ yAxisId = defaultYAxisId,
79
+ visibleStackedData,
80
+ data,
81
+ disableHighlight,
82
+ showMark,
83
+ shape = 'circle',
84
+ hidden
85
+ } = series[seriesId];
86
+ if (hidden) {
87
+ return null;
88
+ }
89
+ const axisIndex = disableHighlight ? undefined : getHighlightedIndex.get(xAxisId);
90
+ const showMarkIndex = showMark === 'start' || showMark === 'end' ? getStartEndMarkIndex(data, showMark) : undefined;
91
+ const highlightedIndex = axisIndex ?? showMarkIndex;
92
+ if (highlightedIndex === undefined || data[highlightedIndex] == null) {
93
+ return null;
94
+ }
95
+ const xScale = getValueToPositionMapper(xAxis[xAxisId].scale);
96
+ const yScale = yAxis[yAxisId].scale;
97
+ const xData = xAxis[xAxisId].data;
98
+ if (xData === undefined) {
99
+ throw new Error(process.env.NODE_ENV !== "production" ? `MUI X Charts: ${xAxisId === DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`} should have a data property to be able to display a line plot. ` + 'The x-axis data defines the positions for each point in the line. ' + 'Provide a data array to the x-axis configuration.' : _formatErrorMessage(10, xAxisId === DEFAULT_X_AXIS_KEY ? 'The first `xAxis`' : `The x-axis with id "${xAxisId}"`));
100
+ }
101
+ const x = xScale(xData[highlightedIndex]);
102
+ const y = yScale(visibleStackedData[highlightedIndex][1]); // This should not be undefined since y should not be a band scale
103
+ if (!instance.isPointInside(x, y)) {
104
+ return null;
105
+ }
106
+ const colorGetter = getColor(series[seriesId], xAxis[xAxisId], yAxis[yAxisId]);
107
+ return /*#__PURE__*/_jsx(Element, _extends({
108
+ seriesId: seriesId,
109
+ color: colorGetter(highlightedIndex),
110
+ x: x,
111
+ y: y,
112
+ shape: shape
113
+ }, slotProps?.lineHighlight), `${seriesId}`);
106
114
  }))
107
115
  }));
108
116
  }
117
+
118
+ /**
119
+ * Returns the index of the first (`'start'`) or last (`'end'`) non-null item, or `-1` if none.
120
+ */
121
+ function getStartEndMarkIndex(data, type) {
122
+ if (type === 'start') {
123
+ const index = data.findIndex(value => value != null);
124
+ return index < 0 ? undefined : index;
125
+ }
126
+ const index = data.findLastIndex(value => value != null);
127
+ return index < 0 ? undefined : index;
128
+ }
109
129
  process.env.NODE_ENV !== "production" ? LineHighlightPlot.propTypes = {
110
130
  // ----------------------------- Warning --------------------------------
111
131
  // | These PropTypes are generated from the TypeScript type definitions |
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { type LineItemIdentifier } from "../models/seriesType/line.mjs";
3
3
  import { type MarkElementProps } from "./MarkElement.mjs";
4
+ import type { MarkPropsOverrides } from "../models/chartsSlotsComponentsProps.mjs";
4
5
  export interface MarkPlotSlots {
5
- mark?: React.JSXElementConstructor<MarkElementProps>;
6
+ mark?: React.JSXElementConstructor<MarkElementProps & MarkPropsOverrides>;
6
7
  }
7
8
  export interface MarkPlotSlotProps {
8
- mark?: Partial<MarkElementProps>;
9
+ mark?: Partial<MarkElementProps> & MarkPropsOverrides;
9
10
  }
10
11
  export interface MarkPlotProps extends React.SVGAttributes<SVGSVGElement>, Pick<MarkElementProps, 'skipAnimation'> {
11
12
  /**
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { type LineItemIdentifier } from "../models/seriesType/line.js";
3
3
  import { type MarkElementProps } from "./MarkElement.js";
4
+ import type { MarkPropsOverrides } from "../models/chartsSlotsComponentsProps.js";
4
5
  export interface MarkPlotSlots {
5
- mark?: React.JSXElementConstructor<MarkElementProps>;
6
+ mark?: React.JSXElementConstructor<MarkElementProps & MarkPropsOverrides>;
6
7
  }
7
8
  export interface MarkPlotSlotProps {
8
- mark?: Partial<MarkElementProps>;
9
+ mark?: Partial<MarkElementProps> & MarkPropsOverrides;
9
10
  }
10
11
  export interface MarkPlotProps extends React.SVGAttributes<SVGSVGElement>, Pick<MarkElementProps, 'skipAnimation'> {
11
12
  /**
@@ -1,10 +1,13 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.evaluateCurveAtAngle = evaluateCurveAtAngle;
7
8
  exports.evaluateCurveY = evaluateCurveY;
9
+ var _bezierEasing = _interopRequireDefault(require("bezier-easing"));
10
+ var _warning = require("@mui/x-internals/warning");
8
11
  var _epsilon = require("../../utils/epsilon");
9
12
  var _getCurve = require("../../internals/getCurve");
10
13
  var _clampAngle = require("../../internals/clampAngle");
@@ -75,22 +78,34 @@ function cubicBezierCoeffs(p0, p1, p2, p3) {
75
78
  }
76
79
 
77
80
  /**
78
- * Find parameter t such that the segment's x(t) ≈ targetX
81
+ * Evaluate y on a segment at the given x.
82
+ *
83
+ * Line segments are interpolated linearly. Bezier segments are normalized so
84
+ * their endpoints become (0, 0) and (1, 1), passed to `bezier-easing`, and
85
+ * the result is mapped back to pixel space.
86
+ *
87
+ * Warns once if a curve produces control points outside the segment's x
88
+ * range.
79
89
  */
80
- function findTForX(segment, targetX) {
90
+ function evaluateSegmentYAtX(segment, targetX) {
91
+ const dx = segment.x1 - segment.x0;
92
+ if (dx === 0) {
93
+ return segment.y0;
94
+ }
95
+ const dy = segment.y1 - segment.y0;
81
96
  if (!isBezierSegment(segment)) {
82
- // Linear segment.
83
- const dx = segment.x1 - segment.x0;
84
- return dx === 0 ? 0 : (targetX - segment.x0) / dx;
97
+ return segment.y0 + dy * (targetX - segment.x0) / dx;
85
98
  }
86
- const xBezierCoeffs = cubicBezierCoeffs(segment.x0, segment.cpx1, segment.cpx2, segment.x1);
87
- const polyToSolve = [...xBezierCoeffs];
88
- polyToSolve[3] -= targetX;
89
- const roots = (0, _cubiqSolver.cubicRoots)(polyToSolve);
90
- if (roots.length > 0) {
91
- return roots[0];
99
+ const nx1 = (segment.cpx1 - segment.x0) / dx;
100
+ const nx2 = (segment.cpx2 - segment.x0) / dx;
101
+ if (process.env.NODE_ENV !== 'production' && (nx1 < 0 || nx1 > 1 || nx2 < 0 || nx2 > 1)) {
102
+ (0, _warning.warnOnce)(`MUI X Charts: a curve segment has control points outside its x range. ` + `Please report the curve type and data at https://github.com/mui/mui-x/issues ` + `so we can support it natively.`);
92
103
  }
93
- return -1;
104
+ const ny1 = dy === 0 ? 0 : (segment.cpy1 - segment.y0) / dy;
105
+ const ny2 = dy === 0 ? 0 : (segment.cpy2 - segment.y0) / dy;
106
+ const ease = (0, _bezierEasing.default)(nx1, ny1, nx2, ny2);
107
+ const nt = (targetX - segment.x0) / dx;
108
+ return segment.y0 + dy * ease(nt);
94
109
  }
95
110
 
96
111
  /**
@@ -161,14 +176,25 @@ function evaluateCurveY(points, targetX, curveType) {
161
176
  const capture = new SegmentCapture();
162
177
  const factory = (0, _getCurve.getCurveFactory)(curveType);
163
178
  const curveInstance = factory(capture);
179
+
180
+ // Track which side of targetX the first point is on, so we detect the
181
+ // crossing regardless of whether x is increasing or decreasing.
182
+ const initialSide = points[0].x > targetX;
183
+ let searchStartIndex = 0;
184
+ let crossingDetected = false;
164
185
  curveInstance.lineStart();
165
186
  for (const p of points) {
187
+ if (!crossingDetected && p.x > targetX !== initialSide) {
188
+ searchStartIndex = Math.max(0, capture.segments.length - 1);
189
+ crossingDetected = true;
190
+ }
166
191
  curveInstance.point(p.x, p.y);
167
192
  }
168
193
  curveInstance.lineEnd();
169
194
 
170
195
  // Find the segment containing targetX.
171
- for (const segment of capture.segments) {
196
+ for (let i = searchStartIndex; i < capture.segments.length; i += 1) {
197
+ const segment = capture.segments[i];
172
198
  if (targetX < segment.x0 + 0.5 && targetX > segment.x0 - 0.5) {
173
199
  return segment.y0;
174
200
  }
@@ -178,8 +204,7 @@ function evaluateCurveY(points, targetX, curveType) {
178
204
  const xMin = Math.min(segment.x0, segment.x1);
179
205
  const xMax = Math.max(segment.x0, segment.x1);
180
206
  if (targetX >= xMin && targetX <= xMax) {
181
- const t = findTForX(segment, targetX);
182
- return evaluateSegmentY(segment, t);
207
+ return evaluateSegmentYAtX(segment, targetX);
183
208
  }
184
209
  }
185
210
  return null;
@@ -1,3 +1,5 @@
1
+ import BezierEasing from 'bezier-easing';
2
+ import { warnOnce } from '@mui/x-internals/warning';
1
3
  import { EPSILON } from "../../utils/epsilon.mjs";
2
4
  import { getCurveFactory } from "../../internals/getCurve.mjs";
3
5
  import { clampAngleRad } from "../../internals/clampAngle.mjs";
@@ -69,22 +71,34 @@ function cubicBezierCoeffs(p0, p1, p2, p3) {
69
71
  }
70
72
 
71
73
  /**
72
- * Find parameter t such that the segment's x(t) ≈ targetX
74
+ * Evaluate y on a segment at the given x.
75
+ *
76
+ * Line segments are interpolated linearly. Bezier segments are normalized so
77
+ * their endpoints become (0, 0) and (1, 1), passed to `bezier-easing`, and
78
+ * the result is mapped back to pixel space.
79
+ *
80
+ * Warns once if a curve produces control points outside the segment's x
81
+ * range.
73
82
  */
74
- function findTForX(segment, targetX) {
83
+ function evaluateSegmentYAtX(segment, targetX) {
84
+ const dx = segment.x1 - segment.x0;
85
+ if (dx === 0) {
86
+ return segment.y0;
87
+ }
88
+ const dy = segment.y1 - segment.y0;
75
89
  if (!isBezierSegment(segment)) {
76
- // Linear segment.
77
- const dx = segment.x1 - segment.x0;
78
- return dx === 0 ? 0 : (targetX - segment.x0) / dx;
90
+ return segment.y0 + dy * (targetX - segment.x0) / dx;
79
91
  }
80
- const xBezierCoeffs = cubicBezierCoeffs(segment.x0, segment.cpx1, segment.cpx2, segment.x1);
81
- const polyToSolve = [...xBezierCoeffs];
82
- polyToSolve[3] -= targetX;
83
- const roots = cubicRoots(polyToSolve);
84
- if (roots.length > 0) {
85
- return roots[0];
92
+ const nx1 = (segment.cpx1 - segment.x0) / dx;
93
+ const nx2 = (segment.cpx2 - segment.x0) / dx;
94
+ if (process.env.NODE_ENV !== 'production' && (nx1 < 0 || nx1 > 1 || nx2 < 0 || nx2 > 1)) {
95
+ warnOnce(`MUI X Charts: a curve segment has control points outside its x range. ` + `Please report the curve type and data at https://github.com/mui/mui-x/issues ` + `so we can support it natively.`);
86
96
  }
87
- return -1;
97
+ const ny1 = dy === 0 ? 0 : (segment.cpy1 - segment.y0) / dy;
98
+ const ny2 = dy === 0 ? 0 : (segment.cpy2 - segment.y0) / dy;
99
+ const ease = BezierEasing(nx1, ny1, nx2, ny2);
100
+ const nt = (targetX - segment.x0) / dx;
101
+ return segment.y0 + dy * ease(nt);
88
102
  }
89
103
 
90
104
  /**
@@ -155,14 +169,25 @@ export function evaluateCurveY(points, targetX, curveType) {
155
169
  const capture = new SegmentCapture();
156
170
  const factory = getCurveFactory(curveType);
157
171
  const curveInstance = factory(capture);
172
+
173
+ // Track which side of targetX the first point is on, so we detect the
174
+ // crossing regardless of whether x is increasing or decreasing.
175
+ const initialSide = points[0].x > targetX;
176
+ let searchStartIndex = 0;
177
+ let crossingDetected = false;
158
178
  curveInstance.lineStart();
159
179
  for (const p of points) {
180
+ if (!crossingDetected && p.x > targetX !== initialSide) {
181
+ searchStartIndex = Math.max(0, capture.segments.length - 1);
182
+ crossingDetected = true;
183
+ }
160
184
  curveInstance.point(p.x, p.y);
161
185
  }
162
186
  curveInstance.lineEnd();
163
187
 
164
188
  // Find the segment containing targetX.
165
- for (const segment of capture.segments) {
189
+ for (let i = searchStartIndex; i < capture.segments.length; i += 1) {
190
+ const segment = capture.segments[i];
166
191
  if (targetX < segment.x0 + 0.5 && targetX > segment.x0 - 0.5) {
167
192
  return segment.y0;
168
193
  }
@@ -172,8 +197,7 @@ export function evaluateCurveY(points, targetX, curveType) {
172
197
  const xMin = Math.min(segment.x0, segment.x1);
173
198
  const xMax = Math.max(segment.x0, segment.x1);
174
199
  if (targetX >= xMin && targetX <= xMax) {
175
- const t = findTForX(segment, targetX);
176
- return evaluateSegmentY(segment, t);
200
+ return evaluateSegmentYAtX(segment, targetX);
177
201
  }
178
202
  }
179
203
  return null;