From a162ca47fc35da2c42f943dab5f6e01ec35bb195 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 26 Nov 2024 16:54:38 +0100 Subject: [PATCH 01/32] WIP --- .../ChartDataProvider/ChartDataProvider.tsx | 43 ++-- .../useChartDataProviderProps.ts | 20 +- .../context/ChartProvider/ChartProvider.tsx | 9 +- .../ChartProvider/ChartProvider.types.ts | 9 +- .../DrawingAreaProvider/DrawingArea.types.ts | 53 ----- .../DrawingAreaContext.tsx | 17 -- .../DrawingAreaProvider.tsx | 44 ---- .../src/context/DrawingAreaProvider/index.ts | 3 - .../plugins/corePlugins/corePlugins.ts | 3 +- .../corePlugins/useChartDimensions/index.ts | 6 + .../useChartDimensions.selectors.ts | 15 ++ .../useChartDimensions/useChartDimensions.ts | 192 ++++++++++++++++++ .../useChartDimensions.types.ts | 97 +++++++++ .../src/internals/plugins/models/plugin.ts | 3 + 14 files changed, 354 insertions(+), 160 deletions(-) delete mode 100644 packages/x-charts/src/context/DrawingAreaProvider/DrawingArea.types.ts delete mode 100644 packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaContext.tsx delete mode 100644 packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaProvider.tsx delete mode 100644 packages/x-charts/src/context/DrawingAreaProvider/index.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index e9c03e79cb78..e6919848c0d7 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { MakeOptional } from '@mui/x-internals/types'; -import { DrawingAreaProvider, DrawingAreaProviderProps } from '../DrawingAreaProvider'; import { SeriesProvider, SeriesProviderProps } from '../SeriesProvider'; import { CartesianProvider, CartesianProviderProps } from '../CartesianProvider'; import { PluginProvider, PluginProviderProps } from '../PluginProvider'; @@ -11,18 +10,17 @@ import { AxisConfig, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from '../.. import { AnimationProvider, AnimationProviderProps } from '../AnimationProvider'; import { ZAxisContextProvider, ZAxisContextProviderProps } from '../ZAxisContextProvider'; import { HighlightedProvider, HighlightedProviderProps } from '../HighlightedProvider'; -import { SizeProvider, SizeProviderProps } from '../SizeProvider'; -import { ChartProvider } from '../ChartProvider'; + +import { ChartProvider, ChartProviderProps } from '../ChartProvider'; export type ChartDataProviderProps = Omit< - SizeProviderProps & - Omit & - Pick & + Omit & Pick & ZAxisContextProviderProps & HighlightedProviderProps & PluginProviderProps & - AnimationProviderProps, + AnimationProviderProps & + ChartProviderProps<[]>['pluginParams'], 'children' > & { /** @@ -43,33 +41,28 @@ export type ChartDataProviderProps = Omit< function ChartDataProvider(props: ChartDataProviderProps) { const { children, - drawingAreaProviderProps, seriesProviderProps, cartesianProviderProps, zAxisContextProps, highlightedProviderProps, pluginProviderProps, animationProviderProps, - sizeProviderProps, + chartProviderProps, } = useChartDataProviderProps(props); return ( - - - - - - - - - {children} - - - - - - - + + + + + + + {children} + + + + + ); } diff --git a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts index a6986cd76bd4..3efa74a96c6a 100644 --- a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts +++ b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts @@ -1,5 +1,4 @@ 'use client'; -import type { DrawingAreaProviderProps } from '../DrawingAreaProvider'; import type { CartesianProviderProps } from '../CartesianProvider'; import type { SeriesProviderProps } from '../SeriesProvider'; import type { ZAxisContextProviderProps } from '../ZAxisContextProvider'; @@ -8,7 +7,7 @@ import { HighlightedProviderProps } from '../HighlightedProvider'; import { useDefaultizeAxis } from './useDefaultizeAxis'; import { PluginProviderProps } from '../PluginProvider'; import { AnimationProviderProps } from '../AnimationProvider'; -import { SizeProviderProps } from '../SizeProvider'; +import { ChartProviderProps } from '../ChartProvider'; export const useChartDataProviderProps = (props: ChartDataProviderProps) => { const { @@ -30,8 +29,13 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { const [defaultizedXAxis, defaultizedYAxis] = useDefaultizeAxis(xAxis, yAxis, dataset); - const drawingAreaProviderProps: Omit = { - margin, + const chartProviderProps: Omit, 'children'> = { + plugins: [], + pluginParams: { + width, + height, + margin, + }, }; const animationProviderProps: Omit = { @@ -64,14 +68,8 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { onHighlightChange, }; - const sizeProviderProps: Omit = { - width, - height, - }; - return { children, - drawingAreaProviderProps, seriesProviderProps, cartesianProviderProps, zAxisContextProps, @@ -80,6 +78,6 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { animationProviderProps, xAxis: defaultizedXAxis, yAxis: defaultizedYAxis, - sizeProviderProps, + chartProviderProps, }; }; diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx index cc29f6764e2d..135cbc2a6502 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx @@ -3,11 +3,14 @@ import * as React from 'react'; import { useCharts } from '../../internals/store/useCharts'; import { ChartProviderProps } from './ChartProvider.types'; import { ChartContext } from './ChartContext'; +import { ChartAnyPluginSignature } from '../../internals/plugins/models'; -function ChartProvider(props: ChartProviderProps) { - const { children } = props; +function ChartProvider( + props: ChartProviderProps, +) { + const { children, plugins = [], pluginParams } = props; - const { contextValue } = useCharts([], {}); + const { contextValue } = useCharts(plugins, pluginParams); return {children}; } diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index feb2fa13caf9..9888b9f04542 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -3,8 +3,11 @@ import { ChartAnyPluginSignature, ChartInstance, ChartPublicAPI, + ConvertSignaturesIntoPlugins, + MergeSignaturesProperty, } from '../../internals/plugins/models'; import { ChartStore } from '../../internals/plugins/utils/ChartStore'; +import { ChartCorePluginSignatures } from '../../internals/plugins/corePlugins'; export type ChartContextValue< TSignatures extends readonly ChartAnyPluginSignature[], @@ -28,8 +31,8 @@ export type ChartContextValue< svgRef: React.RefObject; }; -// export interface ChartProviderProps { -export interface ChartProviderProps { - // value: ChartContextValue; +export interface ChartProviderProps { + plugins: ConvertSignaturesIntoPlugins; + pluginParams: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; children: React.ReactNode; } diff --git a/packages/x-charts/src/context/DrawingAreaProvider/DrawingArea.types.ts b/packages/x-charts/src/context/DrawingAreaProvider/DrawingArea.types.ts deleted file mode 100644 index 58ab5b5a7d3f..000000000000 --- a/packages/x-charts/src/context/DrawingAreaProvider/DrawingArea.types.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from 'react'; -import { LayoutConfig } from '../../models'; - -export interface DrawingAreaProviderProps extends Pick { - children: React.ReactNode; -} - -/** - * Defines the area in which it is possible to draw the charts. - */ -export type DrawingAreaState = { - /** - * The gap between the left border of the SVG and the drawing area. - */ - left: number; - /** - * The gap between the top border of the SVG and the drawing area. - */ - top: number; - /** - * The gap between the bottom border of the SVG and the drawing area. - */ - bottom: number; - /** - * The gap between the right border of the SVG and the drawing area. - */ - right: number; - /** - * The width of the drawing area. - */ - width: number; - /** - * The height of the drawing area. - */ - height: number; - /** - * Checks if a point is inside the drawing area. - * @param {Object} point The point to check. - * @param {number} point.x The x coordinate of the point. - * @param {number} point.y The y coordinate of the point. - * @param {Object} options The options of the check. - * @param {Element} [options.targetElement] The element to check if it is allowed to overflow the drawing area. - * @param {'x' | 'y'} [options.direction] The direction to check. - * @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise. - */ - isPointInside: ( - point: { x: number; y: number }, - options?: { - targetElement?: Element; - direction?: 'x' | 'y'; - }, - ) => boolean; -}; diff --git a/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaContext.tsx b/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaContext.tsx deleted file mode 100644 index 3d0fb05a40b7..000000000000 --- a/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaContext.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; -import * as React from 'react'; -import { DrawingAreaState } from './DrawingArea.types'; - -export const DrawingAreaContext = React.createContext({ - top: 0, - left: 0, - bottom: 0, - right: 0, - height: 300, - width: 400, - isPointInside: () => false, -}); - -if (process.env.NODE_ENV !== 'production') { - DrawingAreaContext.displayName = 'DrawingContext'; -} diff --git a/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaProvider.tsx b/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaProvider.tsx deleted file mode 100644 index 1735812357df..000000000000 --- a/packages/x-charts/src/context/DrawingAreaProvider/DrawingAreaProvider.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client'; -import * as React from 'react'; -import useId from '@mui/utils/useId'; -import useChartDimensions from '../../hooks/useChartDimensions'; -import { DrawingAreaProviderProps, DrawingAreaState } from './DrawingArea.types'; -import { DrawingAreaContext } from './DrawingAreaContext'; -import { useSize } from '../SizeProvider'; - -export function DrawingAreaProvider(props: DrawingAreaProviderProps) { - const { margin, children } = props; - const { width, height } = useSize(); - const drawingArea = useChartDimensions(width, height, margin); - const chartId = useId(); - - const isPointInside = React.useCallback( - ({ x, y }, options) => { - // For element allowed to overflow, wrapping them in make them fully part of the drawing area. - if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) { - return true; - } - - const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width; - const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height; - - if (options?.direction === 'x') { - return isInsideX; - } - - if (options?.direction === 'y') { - return isInsideY; - } - - return isInsideX && isInsideY; - }, - [drawingArea], - ); - - const value = React.useMemo( - () => ({ chartId: chartId ?? '', ...drawingArea, isPointInside }), - [chartId, drawingArea, isPointInside], - ); - - return {children}; -} diff --git a/packages/x-charts/src/context/DrawingAreaProvider/index.ts b/packages/x-charts/src/context/DrawingAreaProvider/index.ts deleted file mode 100644 index 9c3a16617b07..000000000000 --- a/packages/x-charts/src/context/DrawingAreaProvider/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './DrawingArea.types'; -export * from './DrawingAreaProvider'; -export * from './DrawingAreaContext'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts b/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts index f2b8e5ac1ef5..3f08d4150ede 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts @@ -1,11 +1,12 @@ import { ConvertPluginsIntoSignatures } from '../models/helpers'; +import { useChartDimensions } from './useChartDimensions/useChartDimensions'; import { useChartId, UseChartIdParameters } from './useChartId'; /** * Internal plugins that create the tools used by the other plugins. * These plugins are used by the Charts components. */ -export const CHART_CORE_PLUGINS = [useChartId] as const; +export const CHART_CORE_PLUGINS = [useChartId, useChartDimensions] as const; export type ChartCorePluginSignatures = ConvertPluginsIntoSignatures; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts new file mode 100644 index 000000000000..c3fc308d2d8e --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts @@ -0,0 +1,6 @@ +export { useChartDimensions } from './useChartDimensions'; +export type { + UseChartDimensionsSignature, + UseChartDimensionsParameters, + UseChartDimensionsDefaultizedParameters, +} from './useChartDimensions.types'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts new file mode 100644 index 000000000000..fccf28d4cbca --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts @@ -0,0 +1,15 @@ +import { createSelector, ChartRootSelector } from '../../utils/selectors'; +import { UseChartDimensionsSignature } from './useChartDimensions.types'; + +const selectorChartDimensionsState: ChartRootSelector = (state) => + state.dimensions; + +/** + * Get the id attribute of the chart. + * @param {ChartState<[UseChartDimensionsSignature]>} state The state of the chart. + * @returns {string} The id attribute of the chart. + */ +export const selectorChartDrawingArea = createSelector( + selectorChartDimensionsState, + (drawingArea) => drawingArea, +); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts new file mode 100644 index 000000000000..4bcf18767b72 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts @@ -0,0 +1,192 @@ +'use client'; +/* eslint-disable react-compiler/react-compiler */ +import * as React from 'react'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; +import ownerWindow from '@mui/utils/ownerWindow'; +import { DEFAULT_MARGINS } from '../../../../constants'; +import { ChartPlugin } from '../../models'; +import { UseChartDimensionsSignature } from './useChartDimensions.types'; +import { selectorChartDrawingArea } from './useChartDimensions.selectors'; + +const MAX_COMPUTE_RUN = 10; + +export const useChartDimensions: ChartPlugin = ({ + params, + store, + svgRef, +}) => { + const hasInSize = params.width !== undefined && params.height !== undefined; + const stateRef = React.useRef({ displayError: false, initialCompute: true, computeRun: 0 }); + // States only used for the initialization of the size. + const [innerWidth, setInnerWidth] = React.useState(0); + const [innerHeight, setInnerHeight] = React.useState(0); + + const computeSize = React.useCallback(() => { + const mainEl = svgRef?.current; + + if (!mainEl) { + return {}; + } + + const win = ownerWindow(mainEl); + const computedStyle = win.getComputedStyle(mainEl); + + const newHeight = Math.floor(parseFloat(computedStyle.height)) || 0; + const newWidth = Math.floor(parseFloat(computedStyle.width)) || 0; + + store.update((prev) => { + const prevWidth = prev.dimensions.width + prev.dimensions.left + prev.dimensions.right; + const prevHeight = prev.dimensions.height + prev.dimensions.top + prev.dimensions.bottom; + + if (prevWidth === newWidth && prevHeight === newHeight) { + return prev; + } + + return { + ...prev, + dimensions: { + ...prev.dimensions, + width: newWidth - prev.dimensions.left - prev.dimensions.right, + height: newHeight - prev.dimensions.top - prev.dimensions.bottom, + }, + }; + }); + return { + height: newHeight, + width: newWidth, + }; + }, [store, svgRef]); + + React.useEffect(() => { + // Ensure the error detection occurs after the first rendering. + stateRef.current.displayError = true; + }, []); + + // This effect is used to compute the size of the container on the initial render. + // It is not bound to the raf loop to avoid an unwanted "resize" event. + // https://github.com/mui/mui-x/issues/13477#issuecomment-2336634785 + useEnhancedEffect(() => { + // computeRun is used to avoid infinite loops. + if ( + hasInSize || + !stateRef.current.initialCompute || + stateRef.current.computeRun > MAX_COMPUTE_RUN + ) { + return; + } + + const computedSize = computeSize(); + + if (computedSize.width !== innerWidth || computedSize.height !== innerHeight) { + stateRef.current.computeRun += 1; + if (computedSize.width !== undefined) { + setInnerWidth(computedSize.width); + } + if (computedSize.height !== undefined) { + setInnerHeight(computedSize.height); + } + } else if (stateRef.current.initialCompute) { + stateRef.current.initialCompute = false; + } + }, [innerHeight, innerWidth, computeSize, hasInSize]); + + useEnhancedEffect(() => { + if (hasInSize) { + return () => {}; + } + computeSize(); + + const elementToObserve = svgRef.current; + if (typeof ResizeObserver === 'undefined') { + return () => {}; + } + + let animationFrame: number; + const observer = new ResizeObserver(() => { + // See https://github.com/mui/mui-x/issues/8733 + animationFrame = requestAnimationFrame(() => { + computeSize(); + }); + }); + + if (elementToObserve) { + observer.observe(elementToObserve); + } + + return () => { + if (animationFrame) { + cancelAnimationFrame(animationFrame); + } + + if (elementToObserve) { + observer.unobserve(elementToObserve); + } + }; + }, [computeSize, hasInSize, svgRef]); + + if (process.env.NODE_ENV !== 'production') { + if (stateRef.current.displayError && params.width === undefined && innerWidth === 0) { + console.error( + `MUI X: ChartContainer does not have \`width\` prop, and its container has no \`width\` defined.`, + ); + stateRef.current.displayError = false; + } + if (stateRef.current.displayError && params.height === undefined && innerHeight === 0) { + console.error( + `MUI X: ChartContainer does not have \`height\` prop, and its container has no \`height\` defined.`, + ); + stateRef.current.displayError = false; + } + } + + const isPointInside = React.useCallback( + ( + { x, y }: { x: number; y: number }, + options?: { + targetElement?: Element; + direction?: 'x' | 'y'; + }, + ) => { + // For element allowed to overflow, wrapping them in make them fully part of the drawing area. + if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) { + return true; + } + const drawingArea = selectorChartDrawingArea(store.value); + + const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width; + const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height; + + if (options?.direction === 'x') { + return isInsideX; + } + + if (options?.direction === 'y') { + return isInsideY; + } + + return isInsideX && isInsideY; + }, + [store.value], + ); + + return { instance: { isPointInside } }; +}; + +useChartDimensions.params = { + width: true, + height: true, + margin: true, +}; + +useChartDimensions.getDefaultizedParams = ({ params }) => ({ + ...params, + margin: params.margin ?? DEFAULT_MARGINS, +}); + +useChartDimensions.getInitialState = ({ width = 0, height = 0, margin }) => ({ + dimensions: { + ...margin, + width: width - margin.left - margin.right, + height: height - margin.top - margin.bottom, + }, +}); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts new file mode 100644 index 000000000000..e8b713ed1fd4 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts @@ -0,0 +1,97 @@ +import { ChartPluginSignature } from '../../models'; + +export interface ChartMargin { + /** + * The gap between the left border of the SVG and the drawing area. + */ + left: number; + /** + * The gap between the top border of the SVG and the drawing area. + */ + top: number; + /** + * The gap between the bottom border of the SVG and the drawing area. + */ + bottom: number; + /** + * The gap between the right border of the SVG and the drawing area. + */ + right: number; +} + +export interface UseChartDimensionsParameters { + /** + * The width of the chart in px. If not defined, it takes the width of the parent element. + */ + width?: number; + /** + * The height of the chart in px. If not defined, it takes the height of the parent element. + */ + height?: number; + /** + * The margin between the SVG and the drawing area. + * It's used for leaving some space for extra information such as the x- and y-axis or legend. + * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. + */ + margin?: ChartMargin; +} + +export type UseChartDimensionsDefaultizedParameters = UseChartDimensionsParameters & { + margin: ChartMargin; +}; + +export interface UseChartDimensionsState { + dimensions: { + /** + * The gap between the left border of the SVG and the drawing area. + */ + left: number; + /** + * The gap between the top border of the SVG and the drawing area. + */ + top: number; + /** + * The gap between the bottom border of the SVG and the drawing area. + */ + bottom: number; + /** + * The gap between the right border of the SVG and the drawing area. + */ + right: number; + /** + * The width of the drawing area. + */ + width: number; + /** + * The height of the drawing area. + */ + height: number; + }; +} + +export interface UseChartDimensionsInstance { + /** + * Checks if a point is inside the drawing area. + * @param {Object} point The point to check. + * @param {number} point.x The x coordinate of the point. + * @param {number} point.y The y coordinate of the point. + * @param {Object} options The options of the check. + * @param {Element} [options.targetElement] The element to check if it is allowed to overflow the drawing area. + * @param {'x' | 'y'} [options.direction] The direction to check. + * @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise. + */ + isPointInside: ( + point: { x: number; y: number }, + options?: { + targetElement?: Element; + direction?: 'x' | 'y'; + }, + ) => boolean; +} + +export type UseChartDimensionsSignature = ChartPluginSignature<{ + params: UseChartDimensionsParameters; + defaultizedParams: UseChartDimensionsDefaultizedParameters; + state: UseChartDimensionsState; + instance: UseChartDimensionsInstance; +}>; diff --git a/packages/x-charts/src/internals/plugins/models/plugin.ts b/packages/x-charts/src/internals/plugins/models/plugin.ts index 405020c1bff7..92c9d64a3db7 100644 --- a/packages/x-charts/src/internals/plugins/models/plugin.ts +++ b/packages/x-charts/src/internals/plugins/models/plugin.ts @@ -84,4 +84,7 @@ export type ChartPlugin = { (options: ChartPluginOptions): ChartResponse; getInitialState?: (params: ChartUsedDefaultizedParams) => TSignature['state']; params: Record; + getDefaultizedParams?: (options: { + params: ChartUsedParams; + }) => TSignature['defaultizedParams']; }; From 7948389080f9a8432985349df3d447338abb6dee Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 26 Nov 2024 17:17:27 +0100 Subject: [PATCH 02/32] extract params --- .../store/extractPluginParamsFromProps.ts | 50 +++++++++++++++++++ .../x-charts/src/internals/store/useCharts.ts | 9 +++- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 packages/x-charts/src/internals/store/extractPluginParamsFromProps.ts diff --git a/packages/x-charts/src/internals/store/extractPluginParamsFromProps.ts b/packages/x-charts/src/internals/store/extractPluginParamsFromProps.ts new file mode 100644 index 000000000000..f9cb8cb77cf5 --- /dev/null +++ b/packages/x-charts/src/internals/store/extractPluginParamsFromProps.ts @@ -0,0 +1,50 @@ +import { ChartCorePluginSignatures } from '../plugins/corePlugins'; +import { + ChartAnyPluginSignature, + ChartPlugin, + ChartPluginSignature, + ConvertSignaturesIntoPlugins, + MergeSignaturesProperty, +} from '../plugins/models'; +import { UseChartBaseProps } from './useCharts.types'; + +export const extractPluginParamsFromProps = < + TSignatures extends readonly ChartPluginSignature[], + TProps extends Partial>, +>({ + props: { apiRef, ...props }, + plugins, +}: { + props: TProps; + plugins: ConvertSignaturesIntoPlugins; +}) => { + type PluginParams = MergeSignaturesProperty; + + const paramsLookup = {} as Record; + plugins.forEach((plugin) => { + Object.assign(paramsLookup, plugin.params); + }); + + const pluginParams = {} as PluginParams; + + Object.keys(props).forEach((propName) => { + const prop = props[propName as keyof typeof props] as any; + + if (paramsLookup[propName as keyof PluginParams]) { + pluginParams[propName as keyof PluginParams] = prop; + } + }); + + const defaultizedPluginParams = plugins.reduce( + (acc, plugin: ChartPlugin) => { + if (plugin.getDefaultizedParams) { + return plugin.getDefaultizedParams({ params: acc }); + } + + return acc; + }, + pluginParams, + ) as unknown as MergeSignaturesProperty; + + return defaultizedPluginParams; +}; diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index ac61c10a1804..80f12a62facf 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -11,6 +11,7 @@ import { import { CHART_CORE_PLUGINS, ChartCorePluginSignatures } from '../plugins/corePlugins'; import { UseChartBaseProps } from './useCharts.types'; import { UseChartInteractionState } from '../plugins/featurePlugins/useChartInteraction/useChartInteraction.types'; +import { extractPluginParamsFromProps } from './extractPluginParamsFromProps'; export function useChartApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -48,7 +49,11 @@ export function useCharts< [inPlugins], ); - const pluginParams = {}; // To generate when plugins use params. + const pluginParams = extractPluginParamsFromProps({ + plugins, + props, + }); + const instanceRef = React.useRef({} as ChartInstance); const instance = instanceRef.current as ChartInstance; const publicAPI = useChartApiInitialization>(props.apiRef); @@ -70,7 +75,7 @@ export function useCharts< plugins.forEach((plugin) => { if (plugin.getInitialState) { - Object.assign(initialState, plugin.getInitialState({})); + Object.assign(initialState, plugin.getInitialState(pluginParams)); } }); storeRef.current = new ChartStore(initialState); From 5bd1ebe76cf4801674cbe1cea0900e165962ee84 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 27 Nov 2024 11:51:52 +0100 Subject: [PATCH 03/32] continue --- .../ChartDataProviderPro.tsx | 41 +++--- .../useChartDataProviderProProps.ts | 6 +- .../src/context/ZoomProvider/useSetupPan.ts | 18 +-- .../src/context/ZoomProvider/useSetupZoom.ts | 7 +- .../src/ChartContainer/ResizableContainer.tsx | 14 +- .../x-charts/src/ChartsGrid/ChartsGrid.tsx | 14 +- .../src/ChartsGrid/ChartsHorizontalGrid.tsx | 10 +- .../src/ChartsGrid/ChartsVerticalGrid.tsx | 10 +- .../src/ChartsLegend/LegendPerItem.tsx | 5 +- .../src/ChartsSurface/ChartsSurface.tsx | 7 +- .../ChartsVoronoiHandler.tsx | 11 +- .../x-charts/src/ChartsXAxis/ChartsXAxis.tsx | 11 +- .../x-charts/src/ChartsYAxis/ChartsYAxis.tsx | 6 +- .../x-charts/src/Gauge/GaugeContainer.tsx | 81 +++++------- .../src/LineChart/LineHighlightPlot.tsx | 6 +- packages/x-charts/src/LineChart/MarkPlot.tsx | 6 +- packages/x-charts/src/PieChart/PiePlot.tsx | 4 +- .../src/PieChart/getPieCoordinates.ts | 4 +- .../x-charts/src/ScatterChart/Scatter.tsx | 9 +- .../src/SparkLineChart/SparkLineChart.tsx | 4 +- .../context/ChartProvider/ChartProvider.tsx | 2 +- .../ChartProvider/ChartProvider.types.ts | 6 +- .../src/context/SizeProvider/Size.types.ts | 32 ----- .../src/context/SizeProvider/SizeContext.ts | 18 --- .../src/context/SizeProvider/SizeProvider.tsx | 28 ---- .../src/context/SizeProvider/index.ts | 4 - .../useChartContainerDimensions.ts | 122 ------------------ .../src/context/SizeProvider/useSize.ts | 12 -- packages/x-charts/src/hooks/useAxisEvents.ts | 8 +- packages/x-charts/src/hooks/useDrawingArea.ts | 23 ++-- .../src/internals/computeAxisValue.ts | 7 +- packages/x-charts/src/internals/index.ts | 1 - .../useChartDimensions.selectors.ts | 23 +++- .../useChartDimensions/useChartDimensions.ts | 6 +- .../useChartDimensions.types.ts | 2 +- packages/x-charts/src/models/layout.ts | 4 +- 36 files changed, 184 insertions(+), 388 deletions(-) delete mode 100644 packages/x-charts/src/context/SizeProvider/Size.types.ts delete mode 100644 packages/x-charts/src/context/SizeProvider/SizeContext.ts delete mode 100644 packages/x-charts/src/context/SizeProvider/SizeProvider.tsx delete mode 100644 packages/x-charts/src/context/SizeProvider/index.ts delete mode 100644 packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts delete mode 100644 packages/x-charts/src/context/SizeProvider/useSize.ts diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx index 31cb5e114ae8..028e842c502d 100644 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx +++ b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx @@ -3,11 +3,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { ChartDataProviderProps, - DrawingAreaProvider, PluginProvider, SeriesProvider, AnimationProvider, - SizeProvider, ChartProvider, } from '@mui/x-charts/internals'; import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; @@ -24,40 +22,35 @@ export interface ChartDataProviderProProps extends ChartDataProviderProps, ZoomP function ChartDataProviderPro(props: ChartDataProviderProProps) { const { zoomProviderProps, - drawingAreaProviderProps, seriesProviderProps, zAxisContextProps, highlightedProviderProps, cartesianProviderProps, - sizeProviderProps, pluginProviderProps, animationProviderProps, + chartProviderProps, children, } = useChartContainerProProps(props); useLicenseVerifier('x-charts-pro', releaseInfo); return ( - - - - - - - - - - - {children} - - - - - - - - - + + + + + + + + + {children} + + + + + + + ); } diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts b/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts index 39e6726455b1..52a25d542ff5 100644 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts +++ b/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts @@ -8,12 +8,11 @@ export const useChartContainerProProps = (props: ChartDataProviderProProps) => { const { children, - drawingAreaProviderProps, + chartProviderProps, seriesProviderProps, cartesianProviderProps, zAxisContextProps, highlightedProviderProps, - sizeProviderProps, pluginProviderProps, animationProviderProps, xAxis, @@ -30,13 +29,12 @@ export const useChartContainerProProps = (props: ChartDataProviderProProps) => { return { zoomProviderProps, children, - drawingAreaProviderProps, pluginProviderProps, seriesProviderProps, cartesianProviderProps, zAxisContextProps, highlightedProviderProps, - sizeProviderProps, + chartProviderProps, animationProviderProps, }; }; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts index 84d043676a8c..52510e376c23 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts @@ -1,14 +1,15 @@ 'use client'; import * as React from 'react'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { getSVGPoint } from '@mui/x-charts/internals'; + +import { getSVGPoint, useChartContext } from '@mui/x-charts/internals'; import { useZoom } from './useZoom'; import { ZoomData } from './Zoom.types'; export const useSetupPan = () => { const { zoomData, setZoomData, setIsInteracting, isPanEnabled, options } = useZoom(); const drawingArea = useDrawingArea(); - + const { instance } = useChartContext(); const svgRef = useSvgRef(); const isDraggingRef = React.useRef(false); @@ -85,7 +86,7 @@ export const useSetupPan = () => { eventCacheRef.current.push(event); const point = getSVGPoint(element, event); - if (!drawingArea.isPointInside(point)) { + if (!instance.isPointInside(point)) { return; } @@ -127,14 +128,5 @@ export const useSetupPan = () => { document.removeEventListener('pointercancel', handleUp); document.removeEventListener('pointerleave', handleUp); }; - }, [ - drawingArea, - svgRef, - isDraggingRef, - setIsInteracting, - zoomData, - setZoomData, - isPanEnabled, - options, - ]); + }, [instance, svgRef, isDraggingRef, setIsInteracting, zoomData, setZoomData, isPanEnabled, options, drawingArea.width, drawingArea.height]); }; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts index 5f4a50f39530..70b53b847411 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { getSVGPoint } from '@mui/x-charts/internals'; +import { getSVGPoint, useChartContext } from '@mui/x-charts/internals'; import { useZoom } from './useZoom'; import { DefaultizedZoomOptions, ZoomData } from './Zoom.types'; @@ -58,6 +58,7 @@ const zoomAtPoint = ( export const useSetupZoom = () => { const { setZoomData, isZoomEnabled, options, setIsInteracting } = useZoom(); const drawingArea = useDrawingArea(); + const { instance } = useChartContext(); const svgRef = useSvgRef(); const eventCacheRef = React.useRef([]); @@ -77,7 +78,7 @@ export const useSetupZoom = () => { const point = getSVGPoint(element, event); - if (!drawingArea.isPointInside(point)) { + if (!instance.isPointInside(point)) { return; } @@ -217,7 +218,7 @@ export const useSetupZoom = () => { clearTimeout(interactionTimeoutRef.current); } }; - }, [svgRef, setZoomData, drawingArea, isZoomEnabled, options, setIsInteracting]); + }, [svgRef, setZoomData, drawingArea, isZoomEnabled, options, setIsInteracting, instance]); }; /** diff --git a/packages/x-charts/src/ChartContainer/ResizableContainer.tsx b/packages/x-charts/src/ChartContainer/ResizableContainer.tsx index e5c0f57d42a0..58ad04609875 100644 --- a/packages/x-charts/src/ChartContainer/ResizableContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ResizableContainer.tsx @@ -1,8 +1,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; -import { useSize } from '../context/SizeProvider'; -import type { SizeContextState } from '../context/SizeProvider'; +import { useStore } from '../internals/store/useStore'; +import { useSelector } from '../internals/store/useSelector'; +import { selectorChartContainerSize } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors'; /** * Wrapping div that take the shape of its parent. @@ -12,7 +13,7 @@ import type { SizeContextState } from '../context/SizeProvider'; export const ResizableContainerRoot = styled('div', { name: 'MuiResponsiveChart', slot: 'Container', -})<{ ownerState: Partial> }>(({ ownerState }) => ({ +})<{ ownerState: { width?: number; height?: number } }>(({ ownerState }) => ({ width: ownerState.width ?? '100%', height: ownerState.height ?? '100%', display: 'flex', @@ -34,13 +35,14 @@ export const ResizableContainerRoot = styled('div', { * @ignore - do not document. */ function ResizableContainer(props: { children: React.ReactNode }) { - const { inHeight, inWidth, containerRef } = useSize(); + const store = useStore(); + const { height, width } = useSelector(store, selectorChartContainerSize); return ( {props.children} diff --git a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx index b657ae448579..f95237650c59 100644 --- a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx +++ b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx @@ -59,11 +59,21 @@ function ChartsGrid(inProps: ChartsGridProps) { return ( {vertical && ( - + )} {horizontal && ( - + )} ); diff --git a/packages/x-charts/src/ChartsGrid/ChartsHorizontalGrid.tsx b/packages/x-charts/src/ChartsGrid/ChartsHorizontalGrid.tsx index 648a9de08cb6..28854c5ab2fb 100644 --- a/packages/x-charts/src/ChartsGrid/ChartsHorizontalGrid.tsx +++ b/packages/x-charts/src/ChartsGrid/ChartsHorizontalGrid.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { DrawingAreaState } from '../context/DrawingAreaProvider'; import { useTicks } from '../hooks/useTicks'; import { AxisDefaultized, ChartsYAxisProps, ScaleName } from '../models/axis'; import { GridLine } from './styledComponents'; @@ -7,7 +6,8 @@ import { ChartsGridClasses } from './chartsGridClasses'; interface ChartsGridHorizontalProps { axis: AxisDefaultized; - drawingArea: DrawingAreaState; + start: number; + end: number; classes: Partial; } @@ -15,7 +15,7 @@ interface ChartsGridHorizontalProps { * @ignore - internal component. */ export function ChartsGridHorizontal(props: ChartsGridHorizontalProps) { - const { axis, drawingArea, classes } = props; + const { axis, start, end, classes } = props; const { scale, tickNumber, tickInterval } = axis; @@ -28,8 +28,8 @@ export function ChartsGridHorizontal(props: ChartsGridHorizontalProps) { key={`horizontal-${value}`} y1={offset} y2={offset} - x1={drawingArea.left} - x2={drawingArea.left + drawingArea.width} + x1={start} + x2={end} className={classes.horizontalLine} /> ))} diff --git a/packages/x-charts/src/ChartsGrid/ChartsVerticalGrid.tsx b/packages/x-charts/src/ChartsGrid/ChartsVerticalGrid.tsx index 93412ad943c2..170fd9867ddf 100644 --- a/packages/x-charts/src/ChartsGrid/ChartsVerticalGrid.tsx +++ b/packages/x-charts/src/ChartsGrid/ChartsVerticalGrid.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { DrawingAreaState } from '../context/DrawingAreaProvider'; import { useTicks } from '../hooks/useTicks'; import { AxisDefaultized, ChartsXAxisProps, ScaleName } from '../models/axis'; import { GridLine } from './styledComponents'; @@ -7,7 +6,8 @@ import { ChartsGridClasses } from './chartsGridClasses'; interface ChartsGridVerticalProps { axis: AxisDefaultized; - drawingArea: DrawingAreaState; + start: number; + end: number; classes: Partial; } @@ -15,7 +15,7 @@ interface ChartsGridVerticalProps { * @ignore - internal component. */ export function ChartsGridVertical(props: ChartsGridVerticalProps) { - const { axis, drawingArea, classes } = props; + const { axis, start, end, classes } = props; const { scale, tickNumber, tickInterval } = axis; @@ -26,8 +26,8 @@ export function ChartsGridVertical(props: ChartsGridVerticalProps) { {xTicks.map(({ value, offset }) => ( (functi inProps: ChartsSurfaceProps, ref: React.Ref, ) { + const store = useStore(); const { width, height, left, right, top, bottom } = useDrawingArea(); - const { hasIntrinsicSize } = useSize(); + const hasIntrinsicSize = useSelector(store, selectorChartHasIntrinsicSize); const svgRef = useSvgRef(); const handleRef = useForkRef(svgRef, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index 638b9c2577f5..0796b9159b4d 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -10,8 +10,9 @@ import { getSVGPoint } from '../internals/getSVGPoint'; import { ScatterItemIdentifier } from '../models'; import { SeriesId } from '../models/seriesType/common'; import { useDrawingArea, useSvgRef } from '../hooks'; -import { useHighlighted } from '../context'; +import { useHighlighted } from '../context/HighlightedProvider'; import { useScatterSeries } from '../hooks/useSeries'; +import { useChartContext } from '../context/ChartProvider/useChartContext'; export type ChartsVoronoiHandlerProps = { /** @@ -33,6 +34,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { const { voronoiMaxRadius, onItemClick } = props; const svgRef = useSvgRef(); const drawingArea = useDrawingArea(); + const { instance } = useChartContext(); const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); const store = useStore(); @@ -84,7 +86,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { const pointX = getXPosition(x); const pointY = getYPosition(y); - if (!drawingArea.isPointInside({ x: pointX, y: pointY })) { + if (!instance.isPointInside({ x: pointX, y: pointY })) { // If the point is not displayed we move them to a trash coordinate. // This avoids managing index mapping before/after filtering. // The trash point is far enough such that any point in the drawing area will be closer to the mouse than the trash coordinate. @@ -104,7 +106,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { delauneyRef.current = new Delaunay(points); lastFind.current = undefined; - }, [defaultXAxisId, defaultYAxisId, series, seriesOrder, xAxis, yAxis, drawingArea]); + }, [defaultXAxisId, defaultYAxisId, series, seriesOrder, xAxis, yAxis, drawingArea, instance]); React.useEffect(() => { if (svgRef.current === null) { @@ -122,7 +124,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { // Get mouse coordinate in global SVG space const svgPoint = getSVGPoint(element, event); - if (!drawingArea.isPointInside(svgPoint)) { + if (!instance.isPointInside(svgPoint)) { lastFind.current = undefined; return 'outside-chart'; } @@ -234,6 +236,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { clearHighlighted, drawingArea, store, + instance, ]); // eslint-disable-next-line react/jsx-no-useless-fragment diff --git a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx index 579af7bb63bb..efa310dbf16c 100644 --- a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx +++ b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx @@ -16,6 +16,7 @@ import { useDrawingArea } from '../hooks/useDrawingArea'; import { getWordsByLines } from '../internals/getWordsByLines'; import { isInfinity } from '../internals/isInfinity'; import { isBandScale } from '../internals/isBandScale'; +import { useChartContext } from '../context/ChartProvider/useChartContext'; const useUtilityClasses = (ownerState: ChartsXAxisProps & { theme: Theme }) => { const { classes, position } = ownerState; @@ -141,7 +142,8 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { const theme = useTheme(); const classes = useUtilityClasses({ ...defaultizedProps, theme }); - const { left, top, width, height, isPointInside } = useDrawingArea(); + const { left, top, width, height } = useDrawingArea(); + const { instance } = useChartContext(); const tickSize = disableTicks ? 4 : tickSizeProp; @@ -224,8 +226,11 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { const xTickLabel = labelOffset ?? 0; const yTickLabel = positionSign * (tickSize + 3); - const showTick = isPointInside({ x: offset, y: -1 }, { direction: 'x' }); - const showTickLabel = isPointInside({ x: offset + xTickLabel, y: -1 }, { direction: 'x' }); + const showTick = instance.isPointInside({ x: offset, y: -1 }, { direction: 'x' }); + const showTickLabel = instance.isPointInside( + { x: offset + xTickLabel, y: -1 }, + { direction: 'x' }, + ); return ( {!disableTicks && showTick && ( diff --git a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx index f3f626018140..cb3ee2aca6b1 100644 --- a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx +++ b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx @@ -14,6 +14,7 @@ import { ChartsText, ChartsTextProps } from '../ChartsText'; import { getAxisUtilityClass } from '../ChartsAxis/axisClasses'; import { isInfinity } from '../internals/isInfinity'; import { isBandScale } from '../internals/isBandScale'; +import { useChartContext } from '../context/ChartProvider'; const useUtilityClasses = (ownerState: ChartsYAxisProps & { theme: Theme }) => { const { classes, position } = ownerState; @@ -89,7 +90,8 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { const classes = useUtilityClasses({ ...defaultizedProps, theme }); - const { left, top, width, height, isPointInside } = useDrawingArea(); + const { instance } = useChartContext(); + const { left, top, width, height } = useDrawingArea(); const tickSize = disableTicks ? 4 : tickSizeProp; @@ -179,7 +181,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { const skipLabel = typeof tickLabelInterval === 'function' && !tickLabelInterval?.(value, index); - const showLabel = isPointInside({ x: -1, y: offset }, { direction: 'y' }); + const showLabel = instance.isPointInside({ x: -1, y: offset }, { direction: 'y' }); if (!showLabel) { return null; diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index e9896f22106d..c2ecf65b10d6 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -3,23 +3,16 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; -import { DrawingAreaProvider, DrawingAreaProviderProps } from '../context/DrawingAreaProvider'; import { GaugeProvider, GaugeProviderProps } from './GaugeProvider'; -import { SizeProvider, useSize } from '../context/SizeProvider'; +import { useSize } from '../context/SizeProvider'; import { ChartProvider } from '../context/ChartProvider'; +import { MergeSignaturesProperty } from '../internals/plugins/models'; +import { ChartCorePluginSignatures } from '../internals/plugins/corePlugins'; export interface GaugeContainerProps extends Omit, - Pick, + MergeSignaturesProperty, Omit { - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width?: number; - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height?: number; children?: React.ReactNode; } @@ -84,41 +77,37 @@ const GaugeContainer = React.forwardRef(function GaugeContainer( } = props; return ( - - - - - - - - - - + + + + + + ); }); diff --git a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx index d51de6a7ecbf..dc20f67bd128 100644 --- a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx +++ b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx @@ -10,7 +10,7 @@ import { getValueToPositionMapper } from '../hooks/useScale'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import getColor from './getColor'; import { useLineSeries } from '../hooks/useSeries'; -import { useDrawingArea } from '../hooks/useDrawingArea'; +import { useChartContext } from '../context/ChartProvider'; import { selectorChartsInteractionXAxis } from '../internals/plugins/featurePlugins/useChartInteraction'; export interface LineHighlightPlotSlots { @@ -49,7 +49,7 @@ function LineHighlightPlot(props: LineHighlightPlotProps) { const seriesData = useLineSeries(); const axisData = useCartesianContext(); - const drawingArea = useDrawingArea(); + const { instance } = useChartContext(); const store = useStore(); const xAxisIdentifier = useSelector(store, selectorChartsInteractionXAxis); @@ -102,7 +102,7 @@ function LineHighlightPlot(props: LineHighlightPlotProps) { const x = xScale(xData[highlightedIndex]); const y = yScale(stackedData[highlightedIndex][1])!; // This should not be undefined since y should not be a band scale - if (!drawingArea.isPointInside({ x, y })) { + if (!instance.isPointInside({ x, y })) { return null; } diff --git a/packages/x-charts/src/LineChart/MarkPlot.tsx b/packages/x-charts/src/LineChart/MarkPlot.tsx index 7731eba6392f..ab26903a5d57 100644 --- a/packages/x-charts/src/LineChart/MarkPlot.tsx +++ b/packages/x-charts/src/LineChart/MarkPlot.tsx @@ -5,7 +5,6 @@ import { DEFAULT_X_AXIS_KEY } from '../constants'; import { useSkipAnimation } from '../context/AnimationProvider'; import { useCartesianContext } from '../context/CartesianProvider'; import { useChartId } from '../hooks/useChartId'; -import { useDrawingArea } from '../hooks/useDrawingArea'; import { getValueToPositionMapper } from '../hooks/useScale'; import { useLineSeries } from '../hooks/useSeries'; import { cleanId } from '../internals/cleanId'; @@ -13,6 +12,7 @@ import { LineItemIdentifier } from '../models/seriesType/line'; import { CircleMarkElement } from './CircleMarkElement'; import getColor from './getColor'; import { MarkElement, MarkElementProps } from './MarkElement'; +import { useChartContext } from '../context/ChartProvider'; export interface MarkPlotSlots { mark?: React.JSXElementConstructor; @@ -76,7 +76,7 @@ function MarkPlot(props: MarkPlotProps) { const seriesData = useLineSeries(); const axisData = useCartesianContext(); const chartId = useChartId(); - const drawingArea = useDrawingArea(); + const { instance } = useChartContext(); const Mark = slots?.mark ?? (experimentalRendering ? CircleMarkElement : MarkElement); @@ -140,7 +140,7 @@ function MarkPlot(props: MarkPlotProps) { // Remove missing data point return false; } - if (!drawingArea.isPointInside({ x, y })) { + if (!instance.isPointInside({ x, y })) { // Remove out of range return false; } diff --git a/packages/x-charts/src/PieChart/PiePlot.tsx b/packages/x-charts/src/PieChart/PiePlot.tsx index 50190f23472a..9cce72cacefe 100644 --- a/packages/x-charts/src/PieChart/PiePlot.tsx +++ b/packages/x-charts/src/PieChart/PiePlot.tsx @@ -1,13 +1,13 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { DrawingAreaContext } from '../context/DrawingAreaProvider'; import { PieArcPlot, PieArcPlotProps, PieArcPlotSlotProps, PieArcPlotSlots } from './PieArcPlot'; import { PieArcLabelPlotSlots, PieArcLabelPlotSlotProps, PieArcLabelPlot } from './PieArcLabelPlot'; import { getPercentageValue } from '../internals/getPercentageValue'; import { getPieCoordinates } from './getPieCoordinates'; import { usePieSeries } from '../hooks/useSeries'; import { useSkipAnimation } from '../context/AnimationProvider'; +import { useDrawingArea } from '../hooks'; export interface PiePlotSlots extends PieArcPlotSlots, PieArcLabelPlotSlots {} @@ -39,7 +39,7 @@ export interface PiePlotProps extends Pick, - drawing: Pick, + drawing: Pick, ): { cx: number; cy: number; availableRadius: number } { const { height, width } = drawing; const { cx: cxParam, cy: cyParam } = series; diff --git a/packages/x-charts/src/ScatterChart/Scatter.tsx b/packages/x-charts/src/ScatterChart/Scatter.tsx index 431eb57d61eb..84442f07b95b 100644 --- a/packages/x-charts/src/ScatterChart/Scatter.tsx +++ b/packages/x-charts/src/ScatterChart/Scatter.tsx @@ -12,8 +12,8 @@ import { useStore } from '../internals/store/useStore'; import { useSelector } from '../internals/store/useSelector'; import { D3Scale } from '../models/axis'; import { useHighlighted } from '../context'; -import { useDrawingArea } from '../hooks/useDrawingArea'; import { selectorChartsInteractionIsVoronoiEnabled } from '../internals/plugins/featurePlugins/useChartInteraction'; +import { useChartContext } from '../context/ChartProvider'; export interface ScatterProps { series: DefaultizedScatterSeriesType; @@ -46,8 +46,7 @@ export interface ScatterProps { function Scatter(props: ScatterProps) { const { series, xScale, yScale, color, colorGetter, markerSize, onItemClick } = props; - const drawingArea = useDrawingArea(); - + const { instance } = useChartContext(); const store = useStore(); const isVoronoiEnabled = useSelector(store, selectorChartsInteractionIsVoronoiEnabled); @@ -73,7 +72,7 @@ function Scatter(props: ScatterProps) { const x = getXPosition(scatterPoint.x); const y = getYPosition(scatterPoint.y); - const isInRange = drawingArea.isPointInside({ x, y }); + const isInRange = instance.isPointInside({ x, y }); const pointCtx = { type: 'scatter' as const, seriesId: series.id, dataIndex: i }; @@ -100,7 +99,6 @@ function Scatter(props: ScatterProps) { }, [ xScale, yScale, - drawingArea, series.data, series.id, isHighlighted, @@ -108,6 +106,7 @@ function Scatter(props: ScatterProps) { getInteractionItemProps, colorGetter, color, + instance, ]); return ( diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 0499352f5132..53498f3c4c10 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -11,12 +11,12 @@ import { ChartsTooltipSlots, ChartsTooltipSlotProps } from '../ChartsTooltip/Cha import { ChartsAxisHighlight, ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { AxisConfig, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from '../models/axis'; import { LineSeriesType, BarSeriesType } from '../models/seriesType'; -import { CardinalDirections } from '../models/layout'; import { AreaPlotSlots, AreaPlotSlotProps } from '../LineChart/AreaPlot'; import { LinePlotSlots, LinePlotSlotProps } from '../LineChart/LinePlot'; import { MarkPlotSlots, MarkPlotSlotProps } from '../LineChart/MarkPlot'; import { LineHighlightPlotSlots, LineHighlightPlotSlotProps } from '../LineChart/LineHighlightPlot'; import { BarPlotSlots, BarPlotSlotProps } from '../BarChart/BarPlot'; +import { ChartMargin } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types'; export interface SparkLineChartSlots extends AreaPlotSlots, @@ -95,7 +95,7 @@ export interface SparkLineChartProps * right: 5, * } */ - margin?: Partial>; + margin?: Partial; /** * Overridable component slots. * @default {} diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx index 135cbc2a6502..1f8d146a90cc 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx @@ -8,7 +8,7 @@ import { ChartAnyPluginSignature } from '../../internals/plugins/models'; function ChartProvider( props: ChartProviderProps, ) { - const { children, plugins = [], pluginParams } = props; + const { children, plugins = [], pluginParams = {} } = props; const { contextValue } = useCharts(plugins, pluginParams); diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index 9888b9f04542..b980c27c4ce1 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -31,8 +31,8 @@ export type ChartContextValue< svgRef: React.RefObject; }; -export interface ChartProviderProps { - plugins: ConvertSignaturesIntoPlugins; - pluginParams: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; +export interface ChartProviderProps { + plugins?: ConvertSignaturesIntoPlugins; + pluginParams?: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; children: React.ReactNode; } diff --git a/packages/x-charts/src/context/SizeProvider/Size.types.ts b/packages/x-charts/src/context/SizeProvider/Size.types.ts deleted file mode 100644 index 811e5dcd498d..000000000000 --- a/packages/x-charts/src/context/SizeProvider/Size.types.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as React from 'react'; - -export interface SizeProviderProps { - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width?: number; - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height?: number; - children: React.ReactNode; -} - -export interface SizeContextState extends Required> { - /** - * The ref of the container element that the chart is rendered in. - */ - containerRef: React.RefObject; - /** - * If the chart has a defined size. - */ - hasIntrinsicSize: boolean; - /** - * The input height of the chart in px. - */ - inHeight?: number; - /** - * The input width of the chart in px. - */ - inWidth?: number; -} diff --git a/packages/x-charts/src/context/SizeProvider/SizeContext.ts b/packages/x-charts/src/context/SizeProvider/SizeContext.ts deleted file mode 100644 index f9c4b22b7a9c..000000000000 --- a/packages/x-charts/src/context/SizeProvider/SizeContext.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; - -import { Initializable } from '../context.types'; -import { SizeContextState } from './Size.types'; - -export const SizeContext = React.createContext>({ - isInitialized: false, - data: { - hasIntrinsicSize: false, - containerRef: null as any, - height: 0, - width: 0, - }, -}); - -if (process.env.NODE_ENV !== 'production') { - SizeContext.displayName = 'SizeContext'; -} diff --git a/packages/x-charts/src/context/SizeProvider/SizeProvider.tsx b/packages/x-charts/src/context/SizeProvider/SizeProvider.tsx deleted file mode 100644 index 6b42cc557a85..000000000000 --- a/packages/x-charts/src/context/SizeProvider/SizeProvider.tsx +++ /dev/null @@ -1,28 +0,0 @@ -'use client'; -import * as React from 'react'; -import { SizeContext } from './SizeContext'; -import { SizeProviderProps } from './Size.types'; -import { useChartContainerDimensions } from './useChartContainerDimensions'; - -/** - * The size provider. - * - * This differs from the DrawingProvider in that it provides the full size of the container. - * - * This provider is also responsible for resolving the size of the container before rendering and if the parent size changes. - */ -function SizeProvider(props: SizeProviderProps) { - const dimensions = useChartContainerDimensions(props.width, props.height); - - const value = React.useMemo( - () => ({ - isInitialized: true, - data: dimensions, - }), - [dimensions], - ); - - return {props.children}; -} - -export { SizeProvider }; diff --git a/packages/x-charts/src/context/SizeProvider/index.ts b/packages/x-charts/src/context/SizeProvider/index.ts deleted file mode 100644 index dfeb24e47f33..000000000000 --- a/packages/x-charts/src/context/SizeProvider/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './SizeProvider'; -export * from './SizeContext'; -export * from './useSize'; -export * from './Size.types'; diff --git a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts b/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts deleted file mode 100644 index 032af4225d68..000000000000 --- a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts +++ /dev/null @@ -1,122 +0,0 @@ -'use client'; -/* eslint-disable react-compiler/react-compiler */ -import * as React from 'react'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; -import ownerWindow from '@mui/utils/ownerWindow'; - -const MAX_COMPUTE_RUN = 10; - -export const useChartContainerDimensions = (inWidth?: number, inHeight?: number) => { - const hasInSize = inWidth !== undefined && inHeight !== undefined; - const stateRef = React.useRef({ displayError: false, initialCompute: true, computeRun: 0 }); - const rootRef = React.useRef(null); - - const [width, setWidth] = React.useState(0); - const [height, setHeight] = React.useState(0); - - // Adaptation of the `computeSizeAndPublishResizeEvent` from the grid. - const computeSize = React.useCallback(() => { - const mainEl = rootRef?.current; - - if (!mainEl) { - return {}; - } - - const win = ownerWindow(mainEl); - const computedStyle = win.getComputedStyle(mainEl); - - const newHeight = Math.floor(parseFloat(computedStyle.height)) || 0; - const newWidth = Math.floor(parseFloat(computedStyle.width)) || 0; - - setWidth(newWidth); - setHeight(newHeight); - - return { width: newWidth, height: newHeight }; - }, []); - - React.useEffect(() => { - // Ensure the error detection occurs after the first rendering. - stateRef.current.displayError = true; - }, []); - - // This effect is used to compute the size of the container on the initial render. - // It is not bound to the raf loop to avoid an unwanted "resize" event. - // https://github.com/mui/mui-x/issues/13477#issuecomment-2336634785 - useEnhancedEffect(() => { - // computeRun is used to avoid infinite loops. - if ( - hasInSize || - !stateRef.current.initialCompute || - stateRef.current.computeRun > MAX_COMPUTE_RUN - ) { - return; - } - - const computedSize = computeSize(); - if (computedSize.width !== width || computedSize.height !== height) { - stateRef.current.computeRun += 1; - } else if (stateRef.current.initialCompute) { - stateRef.current.initialCompute = false; - } - }, [width, height, computeSize, hasInSize]); - - useEnhancedEffect(() => { - if (hasInSize) { - return () => {}; - } - computeSize(); - - const elementToObserve = rootRef.current; - if (typeof ResizeObserver === 'undefined') { - return () => {}; - } - - let animationFrame: number; - const observer = new ResizeObserver(() => { - // See https://github.com/mui/mui-x/issues/8733 - animationFrame = requestAnimationFrame(() => { - computeSize(); - }); - }); - - if (elementToObserve) { - observer.observe(elementToObserve); - } - - return () => { - if (animationFrame) { - cancelAnimationFrame(animationFrame); - } - - if (elementToObserve) { - observer.unobserve(elementToObserve); - } - }; - }, [computeSize, hasInSize]); - - if (process.env.NODE_ENV !== 'production') { - if (stateRef.current.displayError && inWidth === undefined && width === 0) { - console.error( - `MUI X: ChartContainer does not have \`width\` prop, and its container has no \`width\` defined.`, - ); - stateRef.current.displayError = false; - } - if (stateRef.current.displayError && inHeight === undefined && height === 0) { - console.error( - `MUI X: ChartContainer does not have \`height\` prop, and its container has no \`height\` defined.`, - ); - stateRef.current.displayError = false; - } - } - const finalWidth = inWidth ?? width; - const finalHeight = inHeight ?? height; - - return { - containerRef: rootRef, - width: finalWidth, - height: finalHeight, - hasIntrinsicSize: finalWidth > 0 && finalHeight > 0, - inWidth, - inHeight, - }; -}; diff --git a/packages/x-charts/src/context/SizeProvider/useSize.ts b/packages/x-charts/src/context/SizeProvider/useSize.ts deleted file mode 100644 index 4e7ebb951300..000000000000 --- a/packages/x-charts/src/context/SizeProvider/useSize.ts +++ /dev/null @@ -1,12 +0,0 @@ -'use client'; -import * as React from 'react'; -import { SizeContext } from './SizeContext'; -import { SizeContextState } from './Size.types'; - -/** - * Returns the size of the chart. And the ref of the container element that the chart is rendered in. - */ -export const useSize = (): SizeContextState => { - const { data } = React.useContext(SizeContext); - return data; -}; diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index 9d57cde0890c..b2bbc157e998 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -5,15 +5,15 @@ import { isBandScale } from '../internals/isBandScale'; import { AxisDefaultized } from '../models/axis'; import { getSVGPoint } from '../internals/getSVGPoint'; import { useSvgRef } from './useSvgRef'; -import { useDrawingArea } from './useDrawingArea'; import { useStore } from '../internals/store/useStore'; +import { useChartContext } from '../context/ChartProvider'; function getAsANumber(value: number | Date) { return value instanceof Date ? value.getTime() : value; } export const useAxisEvents = (disableAxisListener: boolean) => { const svgRef = useSvgRef(); - const drawingArea = useDrawingArea(); + const { instance } = useChartContext(); const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); const store = useStore(disableAxisListener); @@ -115,7 +115,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { mousePosition.current.x = svgPoint.x; mousePosition.current.y = svgPoint.y; - if (!drawingArea.isPointInside(svgPoint, { targetElement: event.target as SVGElement })) { + if (!instance.isPointInside(svgPoint, { targetElement: event.target as SVGElement })) { if (mousePosition.current.isInChart) { store.update((prev) => ({ ...prev, @@ -172,5 +172,5 @@ export const useAxisEvents = (disableAxisListener: boolean) => { element.removeEventListener('pointercancel', handleOut); element.removeEventListener('pointerleave', handleOut); }; - }, [svgRef, store, usedYAxis, yAxis, usedXAxis, xAxis, disableAxisListener, drawingArea]); + }, [svgRef, store, usedYAxis, yAxis, usedXAxis, xAxis, disableAxisListener, instance]); }; diff --git a/packages/x-charts/src/hooks/useDrawingArea.ts b/packages/x-charts/src/hooks/useDrawingArea.ts index f45457e90743..611f3331efd0 100644 --- a/packages/x-charts/src/hooks/useDrawingArea.ts +++ b/packages/x-charts/src/hooks/useDrawingArea.ts @@ -1,12 +1,17 @@ 'use client'; -import * as React from 'react'; -import { DrawingAreaContext, DrawingAreaState } from '../context/DrawingAreaProvider'; +import { useStore } from '../internals/store/useStore'; +import { useSelector } from '../internals/store/useSelector'; +import { selectorChartDimensionsState } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors'; -export function useDrawingArea(): DrawingAreaState { - const { left, top, width, height, bottom, right, isPointInside } = - React.useContext(DrawingAreaContext); - return React.useMemo( - () => ({ left, top, width, height, bottom, right, isPointInside }), - [height, left, top, width, bottom, right, isPointInside], - ); +export type ChartDrawingArea = { + top: number; + left: number; + right: number; + bottom: number; + width: number; + height: number; +}; +export function useDrawingArea() { + const store = useStore(); + return useSelector(store, selectorChartDimensionsState); } diff --git a/packages/x-charts/src/internals/computeAxisValue.ts b/packages/x-charts/src/internals/computeAxisValue.ts index 07262f05663e..6c7d27026e3d 100644 --- a/packages/x-charts/src/internals/computeAxisValue.ts +++ b/packages/x-charts/src/internals/computeAxisValue.ts @@ -13,7 +13,7 @@ import { CartesianChartSeriesType } from '../models/seriesType/config'; import { getColorScale, getOrdinalColorScale } from './colorScale'; import { getTickNumber } from '../hooks/useTicks'; import { getScale } from './getScale'; -import { DrawingAreaState } from '../context/DrawingAreaProvider'; + import { FormattedSeries } from '../context/SeriesProvider'; import { zoomScaleRange } from '../context/CartesianProvider/zoom'; import { ExtremumGetter } from '../context/PluginProvider'; @@ -24,9 +24,10 @@ import { GetZoomAxisFilters, } from '../context/CartesianProvider/Cartesian.types'; import { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum'; +import type { ChartDrawingArea } from '../hooks'; function getRange( - drawingArea: DrawingAreaState, + drawingArea: ChartDrawingArea, axisDirection: 'x' | 'y' | 'radius' | 'rotation', axis: AxisConfig< ScaleName, @@ -79,7 +80,7 @@ type ComputeResult = { }; type ComputeCommonParams = { - drawingArea: DrawingAreaState; + drawingArea: ChartDrawingArea; formattedSeries: FormattedSeries; extremumGetters: { [K in CartesianChartSeriesType]?: ExtremumGetter }; zoomData?: ZoomData[]; diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index a41e2313e99f..38494c7bfb6f 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -26,7 +26,6 @@ export * from './computeAxisValue'; // contexts export * from '../context/CartesianProvider'; -export * from '../context/DrawingAreaProvider'; export * from '../context/SeriesProvider'; export * from '../context/ZAxisContextProvider'; export * from '../context/PluginProvider'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts index fccf28d4cbca..cfae4c5da34c 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts @@ -1,15 +1,24 @@ -import { createSelector, ChartRootSelector } from '../../utils/selectors'; +import { ChartRootSelector, createSelector } from '../../utils/selectors'; import { UseChartDimensionsSignature } from './useChartDimensions.types'; -const selectorChartDimensionsState: ChartRootSelector = (state) => - state.dimensions; +export const selectorChartDimensionsState: ChartRootSelector = ( + state, +) => state.dimensions; + +export const selectorChartContainerSize = createSelector( + selectorChartDimensionsState, + (dimensionsState) => ({ + width: dimensionsState.width + dimensionsState.left + dimensionsState.right, + height: dimensionsState.height + dimensionsState.top + dimensionsState.bottom, + }), +); /** * Get the id attribute of the chart. - * @param {ChartState<[UseChartDimensionsSignature]>} state The state of the chart. + * @param {ChartState<[UseChartIdSignature]>} state The state of the chart. * @returns {string} The id attribute of the chart. */ -export const selectorChartDrawingArea = createSelector( - selectorChartDimensionsState, - (drawingArea) => drawingArea, +export const selectorChartHasIntrinsicSize = createSelector( + selectorChartContainerSize, + (svgSize) => svgSize.width > 0 && svgSize.height > 0, ); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts index 4bcf18767b72..47d5dcf017b7 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts @@ -6,7 +6,7 @@ import ownerWindow from '@mui/utils/ownerWindow'; import { DEFAULT_MARGINS } from '../../../../constants'; import { ChartPlugin } from '../../models'; import { UseChartDimensionsSignature } from './useChartDimensions.types'; -import { selectorChartDrawingArea } from './useChartDimensions.selectors'; +import { selectorChartDimensionsState } from './useChartDimensions.selectors'; const MAX_COMPUTE_RUN = 10; @@ -151,7 +151,7 @@ export const useChartDimensions: ChartPlugin = ({ if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) { return true; } - const drawingArea = selectorChartDrawingArea(store.value); + const drawingArea = selectorChartDimensionsState(store.value); const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width; const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height; @@ -180,7 +180,7 @@ useChartDimensions.params = { useChartDimensions.getDefaultizedParams = ({ params }) => ({ ...params, - margin: params.margin ?? DEFAULT_MARGINS, + margin: params.margin ? { ...DEFAULT_MARGINS, ...params.margin } : DEFAULT_MARGINS, }); useChartDimensions.getInitialState = ({ width = 0, height = 0, margin }) => ({ diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts index e8b713ed1fd4..3271eeadd2a6 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts @@ -33,7 +33,7 @@ export interface UseChartDimensionsParameters { * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. */ - margin?: ChartMargin; + margin?: Partial; } export type UseChartDimensionsDefaultizedParameters = UseChartDimensionsParameters & { diff --git a/packages/x-charts/src/models/layout.ts b/packages/x-charts/src/models/layout.ts index 5cf2926569e5..06b1e54a7929 100644 --- a/packages/x-charts/src/models/layout.ts +++ b/packages/x-charts/src/models/layout.ts @@ -1,3 +1,5 @@ +import { ChartMargin } from "../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types"; + export interface CardinalDirections { top?: T; bottom?: T; @@ -14,5 +16,5 @@ export type LayoutConfig = { * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. * @default object Depends on the charts type. */ - margin?: Partial>; + margin?: Partial; }; From 83f736c53621e8d50606382e7dcad32d21433506 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 27 Nov 2024 15:58:36 +0100 Subject: [PATCH 04/32] fix --- packages/x-charts/src/ChartsSurface/ChartsSurface.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 92487fc16aab..38fbb1222c90 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -81,7 +81,7 @@ const ChartsSurface = React.forwardRef(functi return ( Date: Thu, 28 Nov 2024 11:03:33 +0100 Subject: [PATCH 05/32] fix resize --- .../src/ChartsSurface/ChartsSurface.tsx | 7 +++- packages/x-charts/src/hooks/useDrawingArea.ts | 4 +-- .../useChartDimensions.selectors.ts | 12 +++++++ .../useChartDimensions/useChartDimensions.ts | 34 +++++++++++++++++-- .../useChartDimensions.types.ts | 8 +++++ 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 38fbb1222c90..3bc9f77dfd40 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -7,6 +7,9 @@ import { useAxisEvents } from '../hooks/useAxisEvents'; import { ChartsAxesGradients } from '../internals/components/ChartsAxesGradients'; import { useDrawingArea } from '../hooks/useDrawingArea'; import { useSvgRef } from '../hooks/useSvgRef'; +import { useSelector } from '../internals/store/useSelector'; +import { useStore } from '../internals/store/useStore'; +import { selectorChartDimensionsState } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors'; export interface ChartsSurfaceProps { className?: string; @@ -58,7 +61,9 @@ const ChartsSurface = React.forwardRef(functi inProps: ChartsSurfaceProps, ref: React.Ref, ) { + const store = useStore(); const { width, height, left, right, top, bottom } = useDrawingArea(); + const { propsWidth, propsHeight } = useSelector(store, selectorChartDimensionsState); const svgRef = useSvgRef(); const handleRef = useForkRef(svgRef, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); @@ -81,7 +86,7 @@ const ChartsSurface = React.forwardRef(functi return ( state.dimensions; +export const selectorChartContainerDrawingArea = createSelector( + selectorChartDimensionsState, + (dimensionsState) => ({ + width: dimensionsState.width, + left: dimensionsState.left, + right: dimensionsState.right, + height: dimensionsState.height, + top: dimensionsState.top, + bottom: dimensionsState.bottom, + }), +); + export const selectorChartContainerSize = createSelector( selectorChartDimensionsState, (dimensionsState) => ({ diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts index 47d5dcf017b7..e2149d66e55e 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts @@ -57,6 +57,32 @@ export const useChartDimensions: ChartPlugin = ({ }; }, [store, svgRef]); + store.update((prev) => { + if ( + (params.width === undefined || prev.dimensions.propsWidth === params.width) && + (params.height === undefined || prev.dimensions.propsHeight === params.height) + ) { + return prev; + } + + return { + ...prev, + dimensions: { + ...prev.dimensions, + width: + params.width === undefined + ? prev.dimensions.width + : params.width - prev.dimensions.left - prev.dimensions.right, + height: + params.height === undefined + ? prev.dimensions.height + : params.height - prev.dimensions.top - prev.dimensions.bottom, + propsWidth: params.width, + propsHeight: params.height, + }, + }; + }); + React.useEffect(() => { // Ensure the error detection occurs after the first rendering. stateRef.current.displayError = true; @@ -183,10 +209,12 @@ useChartDimensions.getDefaultizedParams = ({ params }) => ({ margin: params.margin ? { ...DEFAULT_MARGINS, ...params.margin } : DEFAULT_MARGINS, }); -useChartDimensions.getInitialState = ({ width = 0, height = 0, margin }) => ({ +useChartDimensions.getInitialState = ({ width, height, margin }) => ({ dimensions: { ...margin, - width: width - margin.left - margin.right, - height: height - margin.top - margin.bottom, + width: width ?? 0 - margin.left - margin.right, + height: height ?? 0 - margin.top - margin.bottom, + propsWidth: width, + propsHeight: height, }, }); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts index 3271eeadd2a6..f6143b300af0 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types.ts @@ -66,6 +66,14 @@ export interface UseChartDimensionsState { * The height of the drawing area. */ height: number; + /** + * The SVG width in px provided by props. + */ + propsWidth: number | undefined; + /** + * The SVG height in px provided by props. + */ + propsHeight: number | undefined; }; } From 85946e79c4d85ed1c35eb1c07a1b4def20a9aa82 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 28 Nov 2024 11:58:11 +0100 Subject: [PATCH 06/32] fixes --- .../src/ChartsSurface/ChartsSurface.tsx | 22 ++++++------------- packages/x-charts/src/hooks/useDrawingArea.ts | 4 ++-- .../x-charts/src/hooks/useSvgRef.test.tsx | 2 +- .../useChartDimensions.selectors.ts | 10 ++++++++- .../useChartDimensions/useChartDimensions.ts | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 3bc9f77dfd40..3ff3ebc87e7c 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -5,11 +5,13 @@ import * as React from 'react'; import useForkRef from '@mui/utils/useForkRef'; import { useAxisEvents } from '../hooks/useAxisEvents'; import { ChartsAxesGradients } from '../internals/components/ChartsAxesGradients'; -import { useDrawingArea } from '../hooks/useDrawingArea'; import { useSvgRef } from '../hooks/useSvgRef'; import { useSelector } from '../internals/store/useSelector'; import { useStore } from '../internals/store/useStore'; -import { selectorChartDimensionsState } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors'; +import { + selectorChartContainerSize, + selectorChartPropsSize, +} from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors'; export interface ChartsSurfaceProps { className?: string; @@ -62,24 +64,14 @@ const ChartsSurface = React.forwardRef(functi ref: React.Ref, ) { const store = useStore(); - const { width, height, left, right, top, bottom } = useDrawingArea(); - const { propsWidth, propsHeight } = useSelector(store, selectorChartDimensionsState); + const { width: svgWidth, height: svgHeight } = useSelector(store, selectorChartContainerSize); + const { width: propsWidth, height: propsHeight } = useSelector(store, selectorChartPropsSize); const svgRef = useSvgRef(); const handleRef = useForkRef(svgRef, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); const { children, disableAxisListener = false, className, title, desc, ...other } = themeProps; - const svgWidth = width + left + right; - const svgHeight = height + top + bottom; - - const svgView = { - width: svgWidth, - height: svgHeight, - x: 0, - y: 0, - }; - const hasIntrinsicSize = svgHeight > 0 && svgWidth > 0; useAxisEvents(disableAxisListener); @@ -87,7 +79,7 @@ const ChartsSurface = React.forwardRef(functi return ( { it('should not throw an error when parent context is present', async () => { function RenderDrawingProvider() { return ( - + ); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts index f839ff786bc3..6590eb9000a4 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors.ts @@ -5,7 +5,7 @@ export const selectorChartDimensionsState: ChartRootSelector state.dimensions; -export const selectorChartContainerDrawingArea = createSelector( +export const selectorChartDrawingArea = createSelector( selectorChartDimensionsState, (dimensionsState) => ({ width: dimensionsState.width, @@ -17,6 +17,14 @@ export const selectorChartContainerDrawingArea = createSelector( }), ); +export const selectorChartPropsSize = createSelector( + selectorChartDimensionsState, + (dimensionsState) => ({ + width: dimensionsState.propsWidth, + height: dimensionsState.propsHeight, + }), +); + export const selectorChartContainerSize = createSelector( selectorChartDimensionsState, (dimensionsState) => ({ diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts index e2149d66e55e..cf726966cb20 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/useChartDimensions.ts @@ -212,8 +212,8 @@ useChartDimensions.getDefaultizedParams = ({ params }) => ({ useChartDimensions.getInitialState = ({ width, height, margin }) => ({ dimensions: { ...margin, - width: width ?? 0 - margin.left - margin.right, - height: height ?? 0 - margin.top - margin.bottom, + width: (width ?? 0) - margin.left - margin.right, + height: (height ?? 0) - margin.top - margin.bottom, propsWidth: width, propsHeight: height, }, From 9e466b6edd6f203d039df8dc04bda4e1928164bc Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 28 Nov 2024 11:58:30 +0100 Subject: [PATCH 07/32] prettier --- .../src/context/ZoomProvider/useSetupPan.ts | 13 ++++++++++++- packages/x-charts/src/models/layout.ts | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts index 52510e376c23..b7dc5212c60c 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts @@ -128,5 +128,16 @@ export const useSetupPan = () => { document.removeEventListener('pointercancel', handleUp); document.removeEventListener('pointerleave', handleUp); }; - }, [instance, svgRef, isDraggingRef, setIsInteracting, zoomData, setZoomData, isPanEnabled, options, drawingArea.width, drawingArea.height]); + }, [ + instance, + svgRef, + isDraggingRef, + setIsInteracting, + zoomData, + setZoomData, + isPanEnabled, + options, + drawingArea.width, + drawingArea.height, + ]); }; diff --git a/packages/x-charts/src/models/layout.ts b/packages/x-charts/src/models/layout.ts index 06b1e54a7929..28c8742faf33 100644 --- a/packages/x-charts/src/models/layout.ts +++ b/packages/x-charts/src/models/layout.ts @@ -1,4 +1,4 @@ -import { ChartMargin } from "../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types"; +import { ChartMargin } from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.types'; export interface CardinalDirections { top?: T; From 867ed2abc5d62ade43eea81b79a765e3c06e7378 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 29 Nov 2024 18:11:00 +0100 Subject: [PATCH 08/32] WORK --- .../x-charts-pro/src/Heatmap/extremums.ts | 4 +- .../x-charts-pro/src/Heatmap/formatter.ts | 4 +- packages/x-charts/src/BarChart/BarPlot.tsx | 12 +- .../x-charts/src/BarChart/extremums.test.ts | 4 +- packages/x-charts/src/BarChart/extremums.ts | 10 +- packages/x-charts/src/BarChart/formatter.ts | 4 +- packages/x-charts/src/BarChart/getColor.ts | 2 +- packages/x-charts/src/BarChart/legend.ts | 2 +- packages/x-charts/src/BarChart/plugin.ts | 7 +- .../ChartContainer/useChartContainerProps.ts | 2 - .../x-charts/src/ChartsAxis/ChartsAxis.tsx | 5 +- .../x-charts/src/ChartsGrid/ChartsGrid.tsx | 5 +- .../src/ChartsLegend/DefaultChartsLegend.tsx | 4 +- packages/x-charts/src/ChartsLegend/useAxis.ts | 6 +- packages/x-charts/src/ChartsLegend/utils.ts | 7 +- .../ChartsOnAxisClickHandler.tsx | 6 +- .../src/ChartsSurface/ChartsSurface.test.tsx | 2 +- .../src/ChartsTooltip/useAxisTooltip.tsx | 6 +- .../src/ChartsTooltip/useItemTooltip.tsx | 6 +- .../ChartsVoronoiHandler.tsx | 6 +- .../x-charts/src/ChartsXAxis/ChartsXAxis.tsx | 4 +- .../x-charts/src/ChartsYAxis/ChartsYAxis.tsx | 4 +- packages/x-charts/src/Gauge/Gauge.test.tsx | 2 +- .../x-charts/src/Gauge/GaugeContainer.tsx | 3 +- packages/x-charts/src/LineChart/AreaPlot.tsx | 9 +- .../src/LineChart/LineHighlightPlot.tsx | 7 +- packages/x-charts/src/LineChart/LinePlot.tsx | 9 +- packages/x-charts/src/LineChart/MarkPlot.tsx | 7 +- packages/x-charts/src/LineChart/extremums.ts | 8 +- .../x-charts/src/LineChart/formatter.test.ts | 4 +- packages/x-charts/src/LineChart/formatter.ts | 4 +- packages/x-charts/src/LineChart/getColor.ts | 2 +- packages/x-charts/src/LineChart/legend.ts | 2 +- packages/x-charts/src/LineChart/plugin.ts | 7 +- packages/x-charts/src/PieChart/formatter.ts | 4 +- packages/x-charts/src/PieChart/getColor.ts | 2 +- packages/x-charts/src/PieChart/legend.ts | 2 +- packages/x-charts/src/PieChart/plugin.ts | 7 +- .../x-charts/src/ScatterChart/ScatterPlot.tsx | 6 +- .../x-charts/src/ScatterChart/extremums.ts | 20 +-- .../x-charts/src/ScatterChart/formatter.ts | 4 +- .../x-charts/src/ScatterChart/getColor.ts | 2 +- packages/x-charts/src/ScatterChart/legend.ts | 2 +- packages/x-charts/src/ScatterChart/plugin.ts | 7 +- .../CartesianProvider/Cartesian.types.ts | 67 --------- .../CartesianProvider/CartesianContext.ts | 18 --- .../CartesianProvider/CartesianProvider.tsx | 59 -------- .../CartesianProvider/getAxisExtremum.ts | 52 ------- .../src/context/CartesianProvider/index.ts | 4 - .../CartesianProvider/useCartesianContext.ts | 9 -- .../ChartDataProvider/ChartDataProvider.tsx | 31 +--- .../useChartDataProviderProps.ts | 38 ++--- .../context/ChartProvider/ChartProvider.tsx | 24 ++- .../ChartProvider/ChartProvider.types.ts | 8 +- .../PluginProvider/ColorProcessor.types.ts | 15 -- .../PluginProvider/ExtremumGetter.types.ts | 35 ----- .../context/PluginProvider/Plugin.types.ts | 34 ----- .../context/PluginProvider/PluginContext.ts | 19 --- .../context/PluginProvider/PluginProvider.tsx | 21 --- .../PluginProvider/SeriesFormatter.types.ts | 37 ----- .../src/context/PluginProvider/index.ts | 12 -- .../context/PluginProvider/mergePlugins.ts | 59 -------- .../PluginProvider/useColorProcessor.ts | 46 +++--- .../PluginProvider/useRadiusExtremumGetter.ts | 28 ---- .../useRotationExtremumGetter.ts | 28 ---- .../PluginProvider/useSeriesFormatter.ts | 28 ---- .../PluginProvider/useXExtremumGetter.ts | 27 ---- .../PluginProvider/useYExtremumGetter.ts | 27 ---- .../context/PolarProvider/PolarProvider.tsx | 104 ++++++------- .../context/PolarProvider/getAxisExtremum.ts | 96 ++++++------ .../context/PolarProvider/usePolarContext.ts | 16 +- .../context/SeriesProvider/Series.types.ts | 29 ---- .../context/SeriesProvider/SeriesContext.ts | 12 -- .../context/SeriesProvider/SeriesProvider.tsx | 34 ----- .../src/context/SeriesProvider/index.ts | 11 -- .../context/SeriesProvider/processSeries.ts | 55 ------- packages/x-charts/src/hooks/useAxis.ts | 28 +++- packages/x-charts/src/hooks/useAxisEvents.ts | 5 +- packages/x-charts/src/hooks/useColorScale.ts | 6 +- .../x-charts/src/hooks/useSeries.test.tsx | 12 +- packages/x-charts/src/hooks/useSeries.ts | 29 ++-- .../ChartsAxesGradients.tsx | 6 +- packages/x-charts/src/internals/index.ts | 9 +- .../plugins/corePlugins/corePlugins.ts | 3 +- .../corePlugins/useChartId/useChartId.ts | 2 +- .../useChartId/useChartId.types.ts | 2 +- .../corePlugins/useChartSeries/index.ts | 6 + .../useChartSeries/processSeries.ts | 63 ++++++++ .../useChartSeries.selectors.ts | 5 + .../useChartSeries/useChartSeries.ts | 52 +++++++ .../useChartSeries/useChartSeries.types.ts | 54 +++++++ .../computeAxisValue.ts | 99 ++++++------- .../useChartCartesianAxis}/defaultizeAxis.ts | 6 +- .../useChartCartesianAxis/getAxisExtremum.ts | 67 +++++++++ .../useChartCartesianAxis/index.ts | 6 + .../useChartCartesianAxis.selectors.ts | 10 ++ .../useChartCartesianAxis.ts | 92 ++++++++++++ .../useChartCartesianAxis.types.ts | 139 ++++++++++++++++++ .../useChartCartesianAxis}/zoom.ts | 0 .../src/internals/plugins/models/index.ts | 1 + .../src/internals/plugins/models/plugin.ts | 9 +- .../seriesConfig/colorProcessor.types.ts | 11 ++ .../seriesConfig/extremumGetter.types.ts | 30 ++++ .../plugins/models/seriesConfig/index.ts | 4 + .../models/seriesConfig/seriesConfig.types.ts | 20 +++ .../seriesConfig/seriesProcessor.types.ts | 32 ++++ .../x-charts/src/internals/store/useCharts.ts | 15 +- .../x-charts/src/internals/store/useStore.ts | 5 +- 108 files changed, 1018 insertions(+), 1125 deletions(-) delete mode 100644 packages/x-charts/src/context/CartesianProvider/Cartesian.types.ts delete mode 100644 packages/x-charts/src/context/CartesianProvider/CartesianContext.ts delete mode 100644 packages/x-charts/src/context/CartesianProvider/CartesianProvider.tsx delete mode 100644 packages/x-charts/src/context/CartesianProvider/getAxisExtremum.ts delete mode 100644 packages/x-charts/src/context/CartesianProvider/index.ts delete mode 100644 packages/x-charts/src/context/CartesianProvider/useCartesianContext.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/ColorProcessor.types.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/ExtremumGetter.types.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/Plugin.types.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/PluginContext.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/PluginProvider.tsx delete mode 100644 packages/x-charts/src/context/PluginProvider/SeriesFormatter.types.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/index.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/mergePlugins.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useRadiusExtremumGetter.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useRotationExtremumGetter.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useSeriesFormatter.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useXExtremumGetter.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useYExtremumGetter.ts delete mode 100644 packages/x-charts/src/context/SeriesProvider/Series.types.ts delete mode 100644 packages/x-charts/src/context/SeriesProvider/SeriesContext.ts delete mode 100644 packages/x-charts/src/context/SeriesProvider/SeriesProvider.tsx delete mode 100644 packages/x-charts/src/context/SeriesProvider/index.ts delete mode 100644 packages/x-charts/src/context/SeriesProvider/processSeries.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/processSeries.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts create mode 100644 packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts rename packages/x-charts/src/internals/{ => plugins/featurePlugins/useChartCartesianAxis}/computeAxisValue.ts (74%) rename packages/x-charts/src/{context/CartesianProvider => internals/plugins/featurePlugins/useChartCartesianAxis}/defaultizeAxis.ts (74%) create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts rename packages/x-charts/src/{context/CartesianProvider => internals/plugins/featurePlugins/useChartCartesianAxis}/zoom.ts (100%) create mode 100644 packages/x-charts/src/internals/plugins/models/seriesConfig/colorProcessor.types.ts create mode 100644 packages/x-charts/src/internals/plugins/models/seriesConfig/extremumGetter.types.ts create mode 100644 packages/x-charts/src/internals/plugins/models/seriesConfig/index.ts create mode 100644 packages/x-charts/src/internals/plugins/models/seriesConfig/seriesConfig.types.ts create mode 100644 packages/x-charts/src/internals/plugins/models/seriesConfig/seriesProcessor.types.ts diff --git a/packages/x-charts-pro/src/Heatmap/extremums.ts b/packages/x-charts-pro/src/Heatmap/extremums.ts index a0bdab36b726..62d57ac625f4 100644 --- a/packages/x-charts-pro/src/Heatmap/extremums.ts +++ b/packages/x-charts-pro/src/Heatmap/extremums.ts @@ -1,6 +1,6 @@ -import { ExtremumGetter } from '@mui/x-charts/internals'; +import { CartesianExtremumGetter } from '@mui/x-charts/internals'; -export const getBaseExtremum: ExtremumGetter<'heatmap'> = (params) => { +export const getBaseExtremum: CartesianExtremumGetter<'heatmap'> = (params) => { const { axis } = params; const minX = Math.min(...(axis.data ?? [])); diff --git a/packages/x-charts-pro/src/Heatmap/formatter.ts b/packages/x-charts-pro/src/Heatmap/formatter.ts index 26fa5f2b2c1f..8cad5a7cc17e 100644 --- a/packages/x-charts-pro/src/Heatmap/formatter.ts +++ b/packages/x-charts-pro/src/Heatmap/formatter.ts @@ -1,7 +1,7 @@ -import { SeriesFormatter, SeriesId } from '@mui/x-charts/internals'; +import { SeriesProcessor, SeriesId } from '@mui/x-charts/internals'; import { DefaultizedHeatmapSeriesType } from '../models/seriesType/heatmap'; -const formatter: SeriesFormatter<'heatmap'> = (params) => { +const formatter: SeriesProcessor<'heatmap'> = (params) => { const { series, seriesOrder } = params; const defaultizedSeries: Record = {}; diff --git a/packages/x-charts/src/BarChart/BarPlot.tsx b/packages/x-charts/src/BarChart/BarPlot.tsx index 33924df041db..4c3df0c27f52 100644 --- a/packages/x-charts/src/BarChart/BarPlot.tsx +++ b/packages/x-charts/src/BarChart/BarPlot.tsx @@ -3,20 +3,19 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTransition } from '@react-spring/web'; import { styled } from '@mui/material/styles'; -import { useCartesianContext } from '../context/CartesianProvider'; import { BarElement, barElementClasses, BarElementSlotProps, BarElementSlots } from './BarElement'; import { AxisDefaultized } from '../models/axis'; import { BarItemIdentifier } from '../models'; import getColor from './getColor'; -import { useChartId, useDrawingArea } from '../hooks'; +import { useChartId, useDrawingArea, useXAxes, useYAxes } from '../hooks'; import { AnimationData, CompletedBarData, MaskData } from './types'; import { BarClipPath } from './BarClipPath'; import { BarLabelItemProps, BarLabelSlotProps, BarLabelSlots } from './BarLabel/BarLabelItem'; import { BarLabelPlot } from './BarLabel/BarLabelPlot'; import { checkScaleErrors } from './checkScaleErrors'; import { useBarSeries } from '../hooks/useSeries'; -import { SeriesFormatterResult } from '../context/PluginProvider'; import { useSkipAnimation } from '../context/AnimationProvider'; +import { SeriesProcessorResult } from '../internals/plugins/models/seriesConfig/seriesProcessor.types'; /** * Solution of the equations @@ -91,13 +90,14 @@ const useAggregatedData = (): { } => { const seriesData = useBarSeries() ?? - ({ series: {}, stackingGroups: [], seriesOrder: [] } as SeriesFormatterResult<'bar'>); - const axisData = useCartesianContext(); + ({ series: {}, stackingGroups: [], seriesOrder: [] } as SeriesProcessorResult<'bar'>); + const drawingArea = useDrawingArea(); const chartId = useChartId(); const { series, stackingGroups } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; diff --git a/packages/x-charts/src/BarChart/extremums.test.ts b/packages/x-charts/src/BarChart/extremums.test.ts index b3d861ddedac..6d27c6ef732e 100644 --- a/packages/x-charts/src/BarChart/extremums.test.ts +++ b/packages/x-charts/src/BarChart/extremums.test.ts @@ -1,11 +1,11 @@ import { expect } from 'chai'; import { getExtremumX } from './extremums'; -import { ExtremumGetter } from '../context/PluginProvider'; +import { CartesianExtremumGetter } from '../internals/plugins/models'; const buildData = ( data: number[], layout: 'vertical' | 'horizontal' = 'vertical', -): Parameters>[0] => { +): Parameters>[0] => { return { series: { id1: { diff --git a/packages/x-charts/src/BarChart/extremums.ts b/packages/x-charts/src/BarChart/extremums.ts index 7d29d237c867..28d4ea2ed6c9 100644 --- a/packages/x-charts/src/BarChart/extremums.ts +++ b/packages/x-charts/src/BarChart/extremums.ts @@ -1,4 +1,4 @@ -import { ExtremumGetter } from '../context/PluginProvider/ExtremumGetter.types'; +import { CartesianExtremumGetter } from "../internals/plugins/models/seriesConfig/extremumGetter.types"; const createResult = (data: any, direction: 'x' | 'y') => { if (direction === 'x') { @@ -7,7 +7,7 @@ const createResult = (data: any, direction: 'x' | 'y') => { return { x: null, y: data }; }; -const getBaseExtremum: ExtremumGetter<'bar'> = (params) => { +const getBaseExtremum: CartesianExtremumGetter<'bar'> = (params) => { const { axis, getFilters, isDefaultAxis } = params; const filter = getFilters?.({ @@ -22,7 +22,7 @@ const getBaseExtremum: ExtremumGetter<'bar'> = (params) => { }; const getValueExtremum = - (direction: 'x' | 'y'): ExtremumGetter<'bar'> => + (direction: 'x' | 'y'): CartesianExtremumGetter<'bar'> => (params) => { const { series, axis, getFilters, isDefaultAxis } = params; @@ -63,7 +63,7 @@ const getValueExtremum = ); }; -export const getExtremumX: ExtremumGetter<'bar'> = (params) => { +export const getExtremumX: CartesianExtremumGetter<'bar'> = (params) => { // Notice that bar should be all horizontal or all vertical. // Don't think it's a problem for now const isHorizontal = Object.keys(params.series).some( @@ -75,7 +75,7 @@ export const getExtremumX: ExtremumGetter<'bar'> = (params) => { return getBaseExtremum(params); }; -export const getExtremumY: ExtremumGetter<'bar'> = (params) => { +export const getExtremumY: CartesianExtremumGetter<'bar'> = (params) => { const isHorizontal = Object.keys(params.series).some( (seriesId) => params.series[seriesId].layout === 'horizontal', ); diff --git a/packages/x-charts/src/BarChart/formatter.ts b/packages/x-charts/src/BarChart/formatter.ts index 64175e646d30..6e6ab02fbc84 100644 --- a/packages/x-charts/src/BarChart/formatter.ts +++ b/packages/x-charts/src/BarChart/formatter.ts @@ -5,11 +5,11 @@ import { getStackingGroups } from '../internals/stackSeries'; import { ChartSeries, DatasetElementType, DatasetType } from '../models/seriesType/config'; import { defaultizeValueFormatter } from '../internals/defaultizeValueFormatter'; import { SeriesId } from '../models/seriesType/common'; -import { SeriesFormatter } from '../context/PluginProvider/SeriesFormatter.types'; +import { SeriesProcessor } from '../internals/plugins/models'; type BarDataset = DatasetType; -const formatter: SeriesFormatter<'bar'> = (params, dataset) => { +const formatter: SeriesProcessor<'bar'> = (params, dataset) => { const { seriesOrder, series } = params; const stackingGroups = getStackingGroups(params); diff --git a/packages/x-charts/src/BarChart/getColor.ts b/packages/x-charts/src/BarChart/getColor.ts index c656a49dd36f..f14dee46bb4a 100644 --- a/packages/x-charts/src/BarChart/getColor.ts +++ b/packages/x-charts/src/BarChart/getColor.ts @@ -1,4 +1,4 @@ -import { ColorProcessor } from '../context/PluginProvider/ColorProcessor.types'; +import { ColorProcessor } from '../internals/plugins/models'; const getColor: ColorProcessor<'bar'> = (series, xAxis, yAxis) => { const verticalLayout = series.layout === 'vertical'; diff --git a/packages/x-charts/src/BarChart/legend.ts b/packages/x-charts/src/BarChart/legend.ts index e2ee7ae8c7e9..9874e7daedf0 100644 --- a/packages/x-charts/src/BarChart/legend.ts +++ b/packages/x-charts/src/BarChart/legend.ts @@ -1,6 +1,6 @@ import { LegendItemParams } from '../ChartsLegend/chartsLegend.types'; -import { LegendGetter } from '../context/PluginProvider'; import { getLabel } from '../internals/getLabel'; +import { LegendGetter } from '../internals/plugins/models'; const legendGetter: LegendGetter<'bar'> = (params) => { const { seriesOrder, series } = params; diff --git a/packages/x-charts/src/BarChart/plugin.ts b/packages/x-charts/src/BarChart/plugin.ts index c719e66c5a8d..c6c04c562539 100644 --- a/packages/x-charts/src/BarChart/plugin.ts +++ b/packages/x-charts/src/BarChart/plugin.ts @@ -1,11 +1,10 @@ -import type { ChartsPlugin } from '../context/PluginProvider'; +import { ChartSeriesTypeConfig } from '../internals/plugins/models/seriesConfig'; import { getExtremumX, getExtremumY } from './extremums'; import formatter from './formatter'; import getColor from './getColor'; -export const plugin: ChartsPlugin<'bar'> = { - seriesType: 'bar', - seriesFormatter: formatter, +export const plugin: ChartSeriesTypeConfig<'bar'> = { + seriesProcessor: formatter, colorProcessor: getColor, xExtremumGetter: getExtremumX, yExtremumGetter: getExtremumY, diff --git a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts index 395a2ff1bc95..12e1a9edc178 100644 --- a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts +++ b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts @@ -26,7 +26,6 @@ export const useChartContainerProps = ( disableAxisListener, highlightedItem, onHighlightChange, - plugins, sx, title, xAxis, @@ -52,7 +51,6 @@ export const useChartContainerProps = ( dataset, highlightedItem, onHighlightChange, - plugins, xAxis, yAxis, zAxis, diff --git a/packages/x-charts/src/ChartsAxis/ChartsAxis.tsx b/packages/x-charts/src/ChartsAxis/ChartsAxis.tsx index e34f231ab416..0e85cf6661d5 100644 --- a/packages/x-charts/src/ChartsAxis/ChartsAxis.tsx +++ b/packages/x-charts/src/ChartsAxis/ChartsAxis.tsx @@ -1,7 +1,6 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { useCartesianContext } from '../context/CartesianProvider'; import { ChartsXAxis } from '../ChartsXAxis'; import { ChartsYAxis } from '../ChartsYAxis'; import { @@ -11,6 +10,7 @@ import { ChartsXAxisProps, ChartsYAxisProps, } from '../models/axis'; +import { useXAxes, useYAxes } from '../hooks'; export interface ChartsAxisProps { /** @@ -87,7 +87,8 @@ const mergeProps = ( */ function ChartsAxis(props: ChartsAxisProps) { const { topAxis, leftAxis, rightAxis, bottomAxis, slots, slotProps } = props; - const { xAxis, xAxisIds, yAxis, yAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); // TODO: use for plotting line without ticks or any thing // const drawingArea = React.useContext(DrawingContext); diff --git a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx index f95237650c59..d4195bad5b19 100644 --- a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx +++ b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx @@ -3,12 +3,12 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import composeClasses from '@mui/utils/composeClasses'; import { useThemeProps } from '@mui/material/styles'; -import { useCartesianContext } from '../context/CartesianProvider'; import { ChartsGridClasses, getChartsGridUtilityClass } from './chartsGridClasses'; import { useDrawingArea } from '../hooks/useDrawingArea'; import { GridRoot } from './styledComponents'; import { ChartsGridVertical } from './ChartsVerticalGrid'; import { ChartsGridHorizontal } from './ChartsHorizontalGrid'; +import { useXAxes, useYAxes } from '../hooks/useAxis'; const useUtilityClasses = ({ classes }: ChartsGridProps) => { const slots = { @@ -49,7 +49,8 @@ function ChartsGrid(inProps: ChartsGridProps) { const drawingArea = useDrawingArea(); const { vertical, horizontal, ...other } = props; - const { xAxis, xAxisIds, yAxis, yAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const classes = useUtilityClasses(props); diff --git a/packages/x-charts/src/ChartsLegend/DefaultChartsLegend.tsx b/packages/x-charts/src/ChartsLegend/DefaultChartsLegend.tsx index ff2c62ade76b..740fda8dcf03 100644 --- a/packages/x-charts/src/ChartsLegend/DefaultChartsLegend.tsx +++ b/packages/x-charts/src/ChartsLegend/DefaultChartsLegend.tsx @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { FormattedSeries } from '../context/SeriesProvider'; import { LegendPerItem, LegendPerItemProps } from './LegendPerItem'; import { LegendItemParams, SeriesLegendItemContext } from './chartsLegend.types'; +import { ProcessedSeries } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.types'; const seriesContextBuilder = (context: LegendItemParams): SeriesLegendItemContext => ({ @@ -16,7 +16,7 @@ const seriesContextBuilder = (context: LegendItemParams): SeriesLegendItemContex export interface LegendRendererProps extends Omit { - series: FormattedSeries; + series: ProcessedSeries; seriesToDisplay: LegendPerItemProps['itemsToDisplay']; /** * Callback fired when a legend item is clicked. diff --git a/packages/x-charts/src/ChartsLegend/useAxis.ts b/packages/x-charts/src/ChartsLegend/useAxis.ts index 0b0411393c12..b72a3cd31357 100644 --- a/packages/x-charts/src/ChartsLegend/useAxis.ts +++ b/packages/x-charts/src/ChartsLegend/useAxis.ts @@ -2,10 +2,9 @@ import * as React from 'react'; import { ZAxisContext } from '../context/ZAxisContextProvider'; import { AxisDefaultized } from '../models/axis'; -import { useCartesianContext } from '../context/CartesianProvider/useCartesianContext'; - import { ZAxisDefaultized } from '../models/z-axis'; import { ColorLegendSelector } from './legend.types'; +import { useXAxes, useYAxes } from '../hooks/useAxis'; /** * Helper to select an axis definition according to its direction and id. @@ -14,7 +13,8 @@ export function useAxis({ axisDirection, axisId, }: ColorLegendSelector): ZAxisDefaultized | AxisDefaultized { - const { xAxis, xAxisIds, yAxis, yAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const { zAxis, zAxisIds } = React.useContext(ZAxisContext); switch (axisDirection) { diff --git a/packages/x-charts/src/ChartsLegend/utils.ts b/packages/x-charts/src/ChartsLegend/utils.ts index 0e4e0bf973c8..a9cfdcf0a55b 100644 --- a/packages/x-charts/src/ChartsLegend/utils.ts +++ b/packages/x-charts/src/ChartsLegend/utils.ts @@ -1,11 +1,10 @@ -import { FormattedSeries } from '../context/SeriesProvider'; import { ChartSeriesType } from '../models/seriesType/config'; -import { LegendGetter } from '../context/PluginProvider'; - import getBarLegend from '../BarChart/legend'; import getScatterLegend from '../ScatterChart/legend'; import getLineLegend from '../LineChart/legend'; import getPieLegend from '../PieChart/legend'; +import { ProcessedSeries } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.types'; +import { LegendGetter } from '../internals/plugins/models/seriesConfig/seriesProcessor.types'; const legendGetter: { [T in ChartSeriesType]?: LegendGetter } = { bar: getBarLegend, @@ -14,7 +13,7 @@ const legendGetter: { [T in ChartSeriesType]?: LegendGetter } = { pie: getPieLegend, }; -export function getSeriesToDisplay(series: FormattedSeries) { +export function getSeriesToDisplay(series: ProcessedSeries) { return (Object.keys(series) as ChartSeriesType[]).flatMap( (seriesType: T) => { const getter = legendGetter[seriesType as T]; diff --git a/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx b/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx index 24b157e3ffe9..5a31cb48df42 100644 --- a/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx +++ b/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx @@ -2,8 +2,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useSeries } from '../hooks/useSeries'; -import { useSvgRef } from '../hooks'; -import { useCartesianContext } from '../context/CartesianProvider'; +import { useSvgRef, useXAxes, useYAxes } from '../hooks'; import { useStore } from '../internals/store/useStore'; export type ChartsAxisData = { @@ -29,7 +28,8 @@ function ChartsOnAxisClickHandler(props: ChartsOnAxisClickHandlerProps) { const series = useSeries(); const store = useStore(); - const { xAxisIds, xAxis, yAxisIds, yAxis } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); React.useEffect(() => { const element = svgRef.current; diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx index ee4f1c07fa15..cac9b6c32c0c 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx @@ -16,7 +16,7 @@ describe('', () => { const ref = React.createRef(); render( - + { identifier: ChartItemIdentifier; @@ -30,7 +30,9 @@ export function useItemTooltip(): null | UseItemToolt const series = useSeries(); - const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); + const { zAxis, zAxisIds } = React.useContext(ZAxisContext); const colorProcessors = useColorProcessor(); diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index db4ccf0e321f..db09c2fdda81 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { Delaunay } from '@mui/x-charts-vendor/d3-delaunay'; import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; -import { useCartesianContext } from '../context/CartesianProvider'; import { getValueToPositionMapper } from '../hooks/useScale'; import { useStore } from '../internals/store/useStore'; import { getSVGPoint } from '../internals/getSVGPoint'; @@ -14,6 +13,7 @@ import { useScatterSeries } from '../hooks/useSeries'; import { useChartContext } from '../context/ChartProvider/useChartContext'; import { useDrawingArea } from '../hooks/useDrawingArea'; import { useSvgRef } from '../hooks/useSvgRef'; +import { useXAxes, useYAxes } from '../hooks'; export type ChartsVoronoiHandlerProps = { /** @@ -36,7 +36,9 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { const svgRef = useSvgRef(); const drawingArea = useDrawingArea(); const { instance } = useChartContext(); - const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); + + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const store = useStore(); diff --git a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx index efa310dbf16c..087c8171ed77 100644 --- a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx +++ b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import useSlotProps from '@mui/utils/useSlotProps'; import composeClasses from '@mui/utils/composeClasses'; import { useThemeProps, useTheme, Theme, styled } from '@mui/material/styles'; -import { useCartesianContext } from '../context/CartesianProvider'; import { useTicks, TickItemType } from '../hooks/useTicks'; import { AxisDefaultized, ChartsXAxisProps } from '../models/axis'; import { getAxisUtilityClass } from '../ChartsAxis/axisClasses'; @@ -17,6 +16,7 @@ import { getWordsByLines } from '../internals/getWordsByLines'; import { isInfinity } from '../internals/isInfinity'; import { isBandScale } from '../internals/isBandScale'; import { useChartContext } from '../context/ChartProvider/useChartContext'; +import { useXAxes } from '../hooks/useAxis'; const useUtilityClasses = (ownerState: ChartsXAxisProps & { theme: Theme }) => { const { classes, position } = ownerState; @@ -108,7 +108,7 @@ const defaultProps = { * - [ChartsXAxis API](https://mui.com/x/api/charts/charts-x-axis/) */ function ChartsXAxis(inProps: ChartsXAxisProps) { - const { xAxisIds, xAxis } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); const { scale: xScale, tickNumber, reverse, ...settings } = xAxis[inProps.axisId ?? xAxisIds[0]]; const isMounted = useMounted(); diff --git a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx index cb3ee2aca6b1..ffdd30258975 100644 --- a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx +++ b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx @@ -5,7 +5,6 @@ import useSlotProps from '@mui/utils/useSlotProps'; import composeClasses from '@mui/utils/composeClasses'; import { useThemeProps, useTheme, Theme, styled } from '@mui/material/styles'; import { useRtl } from '@mui/system/RtlProvider'; -import { useCartesianContext } from '../context/CartesianProvider'; import { useTicks } from '../hooks/useTicks'; import { useDrawingArea } from '../hooks/useDrawingArea'; import { ChartsYAxisProps } from '../models/axis'; @@ -15,6 +14,7 @@ import { getAxisUtilityClass } from '../ChartsAxis/axisClasses'; import { isInfinity } from '../internals/isInfinity'; import { isBandScale } from '../internals/isBandScale'; import { useChartContext } from '../context/ChartProvider'; +import { useYAxes } from '../hooks'; const useUtilityClasses = (ownerState: ChartsYAxisProps & { theme: Theme }) => { const { classes, position } = ownerState; @@ -55,7 +55,7 @@ const defaultProps = { * - [ChartsYAxis API](https://mui.com/x/api/charts/charts-y-axis/) */ function ChartsYAxis(inProps: ChartsYAxisProps) { - const { yAxisIds, yAxis } = useCartesianContext(); + const { yAxisIds, yAxis } = useYAxes(); const { scale: yScale, tickNumber, ...settings } = yAxis[inProps.axisId ?? yAxisIds[0]]; const themedProps = useThemeProps({ props: { ...settings, ...inProps }, name: 'MuiChartsYAxis' }); diff --git a/packages/x-charts/src/Gauge/Gauge.test.tsx b/packages/x-charts/src/Gauge/Gauge.test.tsx index f3d7cf533b0b..cb7b79790456 100644 --- a/packages/x-charts/src/Gauge/Gauge.test.tsx +++ b/packages/x-charts/src/Gauge/Gauge.test.tsx @@ -5,7 +5,7 @@ import { Gauge } from '@mui/x-charts/Gauge'; describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ + describeConformance(, () => ({ classes: {} as any, inheritComponent: 'svg', render, diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index 0cbfbefb08cf..63f206e16d21 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -9,7 +9,7 @@ import { MergeSignaturesProperty } from '../internals/plugins/models'; import { ChartCorePluginSignatures } from '../internals/plugins/corePlugins'; export interface GaugeContainerProps - extends Omit, + extends Omit, MergeSignaturesProperty, Omit, React.SVGProps { @@ -60,6 +60,7 @@ const GaugeContainer = React.forwardRef(function GaugeContainer( width: inWidth, height: inHeight, margin: { left: 10, right: 10, top: 10, bottom: 10, ...margin }, + series: [], }} > { const seriesData = useLineSeries(); - const axisData = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); // This memo prevents odd line chart behavior when hydrating. const allData = React.useMemo(() => { @@ -59,7 +60,7 @@ const useAggregatedData = () => { } const { series, stackingGroups } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; + const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; @@ -142,7 +143,7 @@ const useAggregatedData = () => { }; }); }); - }, [seriesData, axisData]); + }, [seriesData, xAxisIds, yAxisIds, xAxis, yAxis]); return allData; }; diff --git a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx index dc20f67bd128..6c23fbb43cc5 100644 --- a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx +++ b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import { SlotComponentPropsFromProps } from '@mui/x-internals/types'; import { useStore } from '../internals/store/useStore'; import { useSelector } from '../internals/store/useSelector'; -import { useCartesianContext } from '../context/CartesianProvider'; import { LineHighlightElement, LineHighlightElementProps } from './LineHighlightElement'; import { getValueToPositionMapper } from '../hooks/useScale'; import { DEFAULT_X_AXIS_KEY } from '../constants'; @@ -12,6 +11,7 @@ import getColor from './getColor'; import { useLineSeries } from '../hooks/useSeries'; import { useChartContext } from '../context/ChartProvider'; import { selectorChartsInteractionXAxis } from '../internals/plugins/featurePlugins/useChartInteraction'; +import { useXAxes, useYAxes } from '../hooks/useAxis'; export interface LineHighlightPlotSlots { lineHighlight?: React.JSXElementConstructor; @@ -48,7 +48,9 @@ function LineHighlightPlot(props: LineHighlightPlotProps) { const { slots, slotProps, ...other } = props; const seriesData = useLineSeries(); - const axisData = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); + const { instance } = useChartContext(); const store = useStore(); @@ -64,7 +66,6 @@ function LineHighlightPlot(props: LineHighlightPlotProps) { return null; } const { series, stackingGroups } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; diff --git a/packages/x-charts/src/LineChart/LinePlot.tsx b/packages/x-charts/src/LineChart/LinePlot.tsx index b0986bee8d67..1cb23b7c92dd 100644 --- a/packages/x-charts/src/LineChart/LinePlot.tsx +++ b/packages/x-charts/src/LineChart/LinePlot.tsx @@ -3,7 +3,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import { line as d3Line } from '@mui/x-charts-vendor/d3-shape'; -import { useCartesianContext } from '../context/CartesianProvider'; import { LineElement, lineElementClasses, @@ -19,6 +18,7 @@ import { useChartGradient } from '../internals/components/ChartsAxesGradients'; import { useLineSeries } from '../hooks/useSeries'; import { AxisId } from '../models/axis'; import { useSkipAnimation } from '../context/AnimationProvider'; +import { useXAxes, useYAxes } from '../hooks'; export interface LinePlotSlots extends LineElementSlots {} @@ -50,7 +50,9 @@ const LinePlotRoot = styled('g', { const useAggregatedData = () => { const seriesData = useLineSeries(); - const axisData = useCartesianContext(); + + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); // This memo prevents odd line chart behavior when hydrating. const allData = React.useMemo(() => { @@ -59,7 +61,6 @@ const useAggregatedData = () => { } const { series, stackingGroups } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; @@ -121,7 +122,7 @@ const useAggregatedData = () => { }; }); }); - }, [seriesData, axisData]); + }, [seriesData, xAxisIds, yAxisIds, xAxis, yAxis]); return allData; }; diff --git a/packages/x-charts/src/LineChart/MarkPlot.tsx b/packages/x-charts/src/LineChart/MarkPlot.tsx index ab26903a5d57..2b5f01a9dde4 100644 --- a/packages/x-charts/src/LineChart/MarkPlot.tsx +++ b/packages/x-charts/src/LineChart/MarkPlot.tsx @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import * as React from 'react'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import { useSkipAnimation } from '../context/AnimationProvider'; -import { useCartesianContext } from '../context/CartesianProvider'; import { useChartId } from '../hooks/useChartId'; import { getValueToPositionMapper } from '../hooks/useScale'; import { useLineSeries } from '../hooks/useSeries'; @@ -13,6 +12,7 @@ import { CircleMarkElement } from './CircleMarkElement'; import getColor from './getColor'; import { MarkElement, MarkElementProps } from './MarkElement'; import { useChartContext } from '../context/ChartProvider'; +import { useXAxes, useYAxes } from '../hooks'; export interface MarkPlotSlots { mark?: React.JSXElementConstructor; @@ -74,7 +74,9 @@ function MarkPlot(props: MarkPlotProps) { const skipAnimation = useSkipAnimation(inSkipAnimation); const seriesData = useLineSeries(); - const axisData = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); + const chartId = useChartId(); const { instance } = useChartContext(); @@ -84,7 +86,6 @@ function MarkPlot(props: MarkPlotProps) { return null; } const { series, stackingGroups } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; diff --git a/packages/x-charts/src/LineChart/extremums.ts b/packages/x-charts/src/LineChart/extremums.ts index 3330f58e8e6e..cda6234e4fec 100644 --- a/packages/x-charts/src/LineChart/extremums.ts +++ b/packages/x-charts/src/LineChart/extremums.ts @@ -1,6 +1,6 @@ -import { ExtremumGetter, ExtremumFilter } from '../context/PluginProvider/ExtremumGetter.types'; +import { CartesianExtremumFilter, CartesianExtremumGetter } from "../internals/plugins/models/seriesConfig/extremumGetter.types"; -export const getExtremumX: ExtremumGetter<'line'> = (params) => { +export const getExtremumX: CartesianExtremumGetter<'line'> = (params) => { const { axis } = params; const minX = Math.min(...(axis.data ?? [])); @@ -14,7 +14,7 @@ function getSeriesExtremums( getValues: GetValues, data: (number | null)[], stackedData: [number, number][], - filter?: ExtremumFilter, + filter?: CartesianExtremumFilter, ): [number, number] { return stackedData.reduce<[number, number]>( (seriesAcc, stackedValue, index) => { @@ -35,7 +35,7 @@ function getSeriesExtremums( ); } -export const getExtremumY: ExtremumGetter<'line'> = (params) => { +export const getExtremumY: CartesianExtremumGetter<'line'> = (params) => { const { series, axis, isDefaultAxis, getFilters } = params; return Object.keys(series) diff --git a/packages/x-charts/src/LineChart/formatter.test.ts b/packages/x-charts/src/LineChart/formatter.test.ts index fb12a5e406ce..255ebf00516e 100644 --- a/packages/x-charts/src/LineChart/formatter.test.ts +++ b/packages/x-charts/src/LineChart/formatter.test.ts @@ -1,9 +1,9 @@ import { expect } from 'chai'; import lineFormatter from './formatter'; -import { SeriesFormatterParams } from '../context/PluginProvider'; +import { SeriesProcessorParams } from '../internals/plugins/models'; const seriesOrder = ['id1']; -const seriesDataset: SeriesFormatterParams<'line'>['series'] = { +const seriesDataset: SeriesProcessorParams<'line'>['series'] = { id1: { // useless info type: 'line', diff --git a/packages/x-charts/src/LineChart/formatter.ts b/packages/x-charts/src/LineChart/formatter.ts index 9364ed579e3e..8d4ead32d190 100644 --- a/packages/x-charts/src/LineChart/formatter.ts +++ b/packages/x-charts/src/LineChart/formatter.ts @@ -5,10 +5,10 @@ import { getStackingGroups } from '../internals/stackSeries'; import { ChartSeries, DatasetElementType, DatasetType } from '../models/seriesType/config'; import { defaultizeValueFormatter } from '../internals/defaultizeValueFormatter'; import { SeriesId } from '../models/seriesType/common'; -import { SeriesFormatter } from '../context/PluginProvider/SeriesFormatter.types'; +import { SeriesProcessor } from '../internals/plugins/models'; // For now it's a copy past of bar charts formatter, but maybe will diverge later -const formatter: SeriesFormatter<'line'> = (params, dataset) => { +const formatter: SeriesProcessor<'line'> = (params, dataset) => { const { seriesOrder, series } = params; const stackingGroups = getStackingGroups({ ...params, defaultStrategy: { stackOffset: 'none' } }); diff --git a/packages/x-charts/src/LineChart/getColor.ts b/packages/x-charts/src/LineChart/getColor.ts index 7fe1d08b81fe..272efea86fa8 100644 --- a/packages/x-charts/src/LineChart/getColor.ts +++ b/packages/x-charts/src/LineChart/getColor.ts @@ -1,4 +1,4 @@ -import { ColorProcessor } from '../context/PluginProvider/ColorProcessor.types'; +import { ColorProcessor } from '../internals/plugins/models'; const getColor: ColorProcessor<'line'> = (series, xAxis, yAxis) => { const yColorScale = yAxis?.colorScale; diff --git a/packages/x-charts/src/LineChart/legend.ts b/packages/x-charts/src/LineChart/legend.ts index 28d3ae416546..f479c5324e3b 100644 --- a/packages/x-charts/src/LineChart/legend.ts +++ b/packages/x-charts/src/LineChart/legend.ts @@ -1,6 +1,6 @@ import { LegendItemParams } from '../ChartsLegend/chartsLegend.types'; import { getLabel } from '../internals/getLabel'; -import { LegendGetter } from '../context/PluginProvider'; +import { LegendGetter } from '../internals/plugins/models'; const legendGetter: LegendGetter<'line'> = (params) => { const { seriesOrder, series } = params; diff --git a/packages/x-charts/src/LineChart/plugin.ts b/packages/x-charts/src/LineChart/plugin.ts index 8acf2ee73da9..70096c5ccf09 100644 --- a/packages/x-charts/src/LineChart/plugin.ts +++ b/packages/x-charts/src/LineChart/plugin.ts @@ -1,12 +1,11 @@ -import type { ChartsPlugin } from '../context/PluginProvider'; +import { ChartSeriesTypeConfig } from '../internals/plugins/models/seriesConfig'; import { getExtremumX, getExtremumY } from './extremums'; import formatter from './formatter'; import getColor from './getColor'; -export const plugin: ChartsPlugin<'line'> = { - seriesType: 'line', +export const plugin: ChartSeriesTypeConfig<'line'> = { colorProcessor: getColor, - seriesFormatter: formatter, + seriesProcessor: formatter, xExtremumGetter: getExtremumX, yExtremumGetter: getExtremumY, }; diff --git a/packages/x-charts/src/PieChart/formatter.ts b/packages/x-charts/src/PieChart/formatter.ts index a8c46b2e369b..22df52087fdb 100644 --- a/packages/x-charts/src/PieChart/formatter.ts +++ b/packages/x-charts/src/PieChart/formatter.ts @@ -3,7 +3,7 @@ import { ChartSeriesDefaultized } from '../models/seriesType/config'; import { ChartsPieSorting, PieValueType } from '../models/seriesType/pie'; import { SeriesId } from '../models/seriesType/common'; import { getLabel } from '../internals/getLabel'; -import { SeriesFormatter } from '../context/PluginProvider/SeriesFormatter.types'; +import { SeriesProcessor } from '../internals/plugins/models'; const getSortingComparator = (comparator: ChartsPieSorting = 'none') => { if (typeof comparator === 'function') { @@ -21,7 +21,7 @@ const getSortingComparator = (comparator: ChartsPieSorting = 'none') => { } }; -const formatter: SeriesFormatter<'pie'> = (params) => { +const formatter: SeriesProcessor<'pie'> = (params) => { const { seriesOrder, series } = params; const defaultizedSeries: Record> = {}; diff --git a/packages/x-charts/src/PieChart/getColor.ts b/packages/x-charts/src/PieChart/getColor.ts index d66320a4e00c..352150585705 100644 --- a/packages/x-charts/src/PieChart/getColor.ts +++ b/packages/x-charts/src/PieChart/getColor.ts @@ -1,4 +1,4 @@ -import { ColorProcessor } from '../context/PluginProvider/ColorProcessor.types'; +import { ColorProcessor } from '../internals/plugins/models'; const getColor: ColorProcessor<'pie'> = (series) => { return (dataIndex: number) => { diff --git a/packages/x-charts/src/PieChart/legend.ts b/packages/x-charts/src/PieChart/legend.ts index 4d39cdd7235e..24bbb0f1cb8b 100644 --- a/packages/x-charts/src/PieChart/legend.ts +++ b/packages/x-charts/src/PieChart/legend.ts @@ -1,6 +1,6 @@ import { LegendItemParams } from '../ChartsLegend/chartsLegend.types'; import { getLabel } from '../internals/getLabel'; -import { LegendGetter } from '../context/PluginProvider'; +import { LegendGetter } from '../internals/plugins/models'; const legendGetter: LegendGetter<'pie'> = (params) => { const { seriesOrder, series } = params; diff --git a/packages/x-charts/src/PieChart/plugin.ts b/packages/x-charts/src/PieChart/plugin.ts index 8b4104ef9bc1..56b427be8f84 100644 --- a/packages/x-charts/src/PieChart/plugin.ts +++ b/packages/x-charts/src/PieChart/plugin.ts @@ -1,9 +1,8 @@ -import type { ChartsPlugin } from '../context/PluginProvider'; +import { ChartSeriesTypeConfig } from '../internals/plugins/models/seriesConfig'; import formatter from './formatter'; import getColor from './getColor'; -export const plugin: ChartsPlugin<'pie'> = { - seriesType: 'pie', +export const plugin: ChartSeriesTypeConfig<'pie'> = { colorProcessor: getColor, - seriesFormatter: formatter, + seriesProcessor: formatter, }; diff --git a/packages/x-charts/src/ScatterChart/ScatterPlot.tsx b/packages/x-charts/src/ScatterChart/ScatterPlot.tsx index 639121a8c79e..76d8f0d7a0ba 100644 --- a/packages/x-charts/src/ScatterChart/ScatterPlot.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterPlot.tsx @@ -2,10 +2,10 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { Scatter, ScatterProps } from './Scatter'; -import { useCartesianContext } from '../context/CartesianProvider'; import getColor from './getColor'; import { ZAxisContext } from '../context/ZAxisContextProvider'; import { useScatterSeries } from '../hooks/useSeries'; +import { useXAxes, useYAxes } from '../hooks'; export interface ScatterPlotSlots { scatter?: React.JSXElementConstructor; @@ -41,14 +41,14 @@ export interface ScatterPlotProps extends Pick { function ScatterPlot(props: ScatterPlotProps) { const { slots, slotProps, onItemClick } = props; const seriesData = useScatterSeries(); - const axisData = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const { zAxis, zAxisIds } = React.useContext(ZAxisContext); if (seriesData === undefined) { return null; } const { series, seriesOrder } = seriesData; - const { xAxis, yAxis, xAxisIds, yAxisIds } = axisData; const defaultXAxisId = xAxisIds[0]; const defaultYAxisId = yAxisIds[0]; diff --git a/packages/x-charts/src/ScatterChart/extremums.ts b/packages/x-charts/src/ScatterChart/extremums.ts index e70482eaf3b2..b5ca57732f84 100644 --- a/packages/x-charts/src/ScatterChart/extremums.ts +++ b/packages/x-charts/src/ScatterChart/extremums.ts @@ -1,16 +1,16 @@ import { - ExtremumGetter, - ExtremumGetterResult, -} from '../context/PluginProvider/ExtremumGetter.types'; + CartesianExtremumGetter, + CartesianExtremumGetterResult, +} from '../internals/plugins/models/seriesConfig/extremumGetter.types'; const mergeMinMax = ( - acc: ExtremumGetterResult, - val: ExtremumGetterResult, -): ExtremumGetterResult => { + acc: CartesianExtremumGetterResult, + val: CartesianExtremumGetterResult, +): CartesianExtremumGetterResult => { return [Math.min(acc[0], val[0]), Math.max(acc[1], val[1])]; }; -export const getExtremumX: ExtremumGetter<'scatter'> = (params) => { +export const getExtremumX: CartesianExtremumGetter<'scatter'> = (params) => { const { series, axis, isDefaultAxis, getFilters } = params; return Object.keys(series) @@ -27,7 +27,7 @@ export const getExtremumX: ExtremumGetter<'scatter'> = (params) => { seriesYAxisId: series[seriesId].yAxisId, }); - const seriesMinMax = series[seriesId].data?.reduce( + const seriesMinMax = series[seriesId].data?.reduce( (accSeries, d, dataIndex) => { if (filter && !filter(d, dataIndex)) { return accSeries; @@ -42,7 +42,7 @@ export const getExtremumX: ExtremumGetter<'scatter'> = (params) => { ); }; -export const getExtremumY: ExtremumGetter<'scatter'> = (params) => { +export const getExtremumY: CartesianExtremumGetter<'scatter'> = (params) => { const { series, axis, isDefaultAxis, getFilters } = params; return Object.keys(series) @@ -59,7 +59,7 @@ export const getExtremumY: ExtremumGetter<'scatter'> = (params) => { seriesYAxisId: series[seriesId].yAxisId, }); - const seriesMinMax = series[seriesId].data?.reduce( + const seriesMinMax = series[seriesId].data?.reduce( (accSeries, d, dataIndex) => { if (filter && !filter(d, dataIndex)) { return accSeries; diff --git a/packages/x-charts/src/ScatterChart/formatter.ts b/packages/x-charts/src/ScatterChart/formatter.ts index 60c024f88c2e..aebb412d646a 100644 --- a/packages/x-charts/src/ScatterChart/formatter.ts +++ b/packages/x-charts/src/ScatterChart/formatter.ts @@ -1,7 +1,7 @@ -import { SeriesFormatter } from '../context/PluginProvider/SeriesFormatter.types'; import { ScatterValueType } from '../models'; +import { SeriesProcessor } from '../internals/plugins/models'; -const formatter: SeriesFormatter<'scatter'> = ({ series, seriesOrder }, dataset) => { +const formatter: SeriesProcessor<'scatter'> = ({ series, seriesOrder }, dataset) => { const completeSeries = Object.fromEntries( Object.entries(series).map(([seriesId, seriesData]) => { const datasetKeys = seriesData?.datasetKeys; diff --git a/packages/x-charts/src/ScatterChart/getColor.ts b/packages/x-charts/src/ScatterChart/getColor.ts index 37b702d2875b..2e57ff5e822a 100644 --- a/packages/x-charts/src/ScatterChart/getColor.ts +++ b/packages/x-charts/src/ScatterChart/getColor.ts @@ -1,4 +1,4 @@ -import { ColorProcessor } from '../context/PluginProvider/ColorProcessor.types'; +import { ColorProcessor } from '../internals/plugins/models'; const getColor: ColorProcessor<'scatter'> = (series, xAxis, yAxis, zAxis) => { const zColorScale = zAxis?.colorScale; diff --git a/packages/x-charts/src/ScatterChart/legend.ts b/packages/x-charts/src/ScatterChart/legend.ts index 6a113642caf2..1db6275f55a0 100644 --- a/packages/x-charts/src/ScatterChart/legend.ts +++ b/packages/x-charts/src/ScatterChart/legend.ts @@ -1,6 +1,6 @@ import { LegendItemParams } from '../ChartsLegend/chartsLegend.types'; import { getLabel } from '../internals/getLabel'; -import { LegendGetter } from '../context/PluginProvider'; +import { LegendGetter } from '../internals/plugins/models'; const legendGetter: LegendGetter<'scatter'> = (params) => { const { seriesOrder, series } = params; diff --git a/packages/x-charts/src/ScatterChart/plugin.ts b/packages/x-charts/src/ScatterChart/plugin.ts index 84bf6a862076..b6753dd88062 100644 --- a/packages/x-charts/src/ScatterChart/plugin.ts +++ b/packages/x-charts/src/ScatterChart/plugin.ts @@ -1,11 +1,10 @@ -import type { ChartsPlugin } from '../context/PluginProvider'; +import { ChartSeriesTypeConfig } from '../internals/plugins/models/seriesConfig'; import { getExtremumX, getExtremumY } from './extremums'; import formatter from './formatter'; import getColor from './getColor'; -export const plugin: ChartsPlugin<'scatter'> = { - seriesType: 'scatter', - seriesFormatter: formatter, +export const plugin: ChartSeriesTypeConfig<'scatter'> = { + seriesProcessor: formatter, colorProcessor: getColor, xExtremumGetter: getExtremumX, yExtremumGetter: getExtremumY, diff --git a/packages/x-charts/src/context/CartesianProvider/Cartesian.types.ts b/packages/x-charts/src/context/CartesianProvider/Cartesian.types.ts deleted file mode 100644 index 7f7244cd55cb..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/Cartesian.types.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { DatasetType } from '../../models/seriesType/config'; -import { - AxisDefaultized, - ScaleName, - ChartsXAxisProps, - ChartsYAxisProps, - AxisId, - AxisConfig, -} from '../../models/axis'; -import { ExtremumFilter } from '../PluginProvider'; - -export type CartesianProviderProps = { - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: AxisConfig[]; - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: AxisConfig[]; - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset?: DatasetType; - children: React.ReactNode; -}; - -export type DefaultizedAxisConfig = { - [axisId: AxisId]: AxisDefaultized; -}; - -export type CartesianContextState = { - /** - * Mapping from x-axis key to scaling configuration. - */ - xAxis: DefaultizedAxisConfig; - /** - * Mapping from y-axis key to scaling configuration. - */ - yAxis: DefaultizedAxisConfig; - /** - * The x-axes IDs sorted by order they got provided. - */ - xAxisIds: AxisId[]; - /** - * The y-axes IDs sorted by order they got provided. - */ - yAxisIds: AxisId[]; -}; - -export type ZoomData = { axisId: AxisId; start: number; end: number }; - -export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; -export type ZoomOptions = Record; - -export type ZoomAxisFilters = Record; - -export type GetZoomAxisFilters = (params: { - currentAxisId: AxisId | undefined; - seriesXAxisId?: AxisId; - seriesYAxisId?: AxisId; - isDefaultAxis: boolean; -}) => ExtremumFilter; diff --git a/packages/x-charts/src/context/CartesianProvider/CartesianContext.ts b/packages/x-charts/src/context/CartesianProvider/CartesianContext.ts deleted file mode 100644 index fb71cc5fdd55..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/CartesianContext.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; - -import { Initializable } from '../context.types'; -import { CartesianContextState } from './Cartesian.types'; - -export const CartesianContext = React.createContext>({ - isInitialized: false, - data: { - xAxis: {}, - yAxis: {}, - xAxisIds: [], - yAxisIds: [], - }, -}); - -if (process.env.NODE_ENV !== 'production') { - CartesianContext.displayName = 'CartesianContext'; -} diff --git a/packages/x-charts/src/context/CartesianProvider/CartesianProvider.tsx b/packages/x-charts/src/context/CartesianProvider/CartesianProvider.tsx deleted file mode 100644 index 6ef033c96f8f..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/CartesianProvider.tsx +++ /dev/null @@ -1,59 +0,0 @@ -'use client'; -import * as React from 'react'; -import { computeAxisValue } from '../../internals/computeAxisValue'; -import { useDrawingArea } from '../../hooks/useDrawingArea'; -import { useSeries } from '../../hooks/useSeries'; -import { CartesianContext } from './CartesianContext'; -import { useXExtremumGetter } from '../PluginProvider/useXExtremumGetter'; -import { useYExtremumGetter } from '../PluginProvider'; -import { CartesianProviderProps } from './Cartesian.types'; - -function CartesianProvider(props: CartesianProviderProps) { - const { xAxis, yAxis, children } = props; - - const formattedSeries = useSeries(); - const drawingArea = useDrawingArea(); - const xExtremumGetters = useXExtremumGetter(); - const yExtremumGetters = useYExtremumGetter(); - - const xValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: xAxis, - extremumGetters: xExtremumGetters, - axisDirection: 'x', - }), - [drawingArea, formattedSeries, xAxis, xExtremumGetters], - ); - - const yValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: yAxis, - extremumGetters: yExtremumGetters, - axisDirection: 'y', - }), - [drawingArea, formattedSeries, yAxis, yExtremumGetters], - ); - - const value = React.useMemo( - () => ({ - isInitialized: true, - data: { - xAxis: xValues.axis, - yAxis: yValues.axis, - xAxisIds: xValues.axisIds, - yAxisIds: yValues.axisIds, - }, - }), - [xValues, yValues], - ); - - return {children}; -} - -export { CartesianProvider }; diff --git a/packages/x-charts/src/context/CartesianProvider/getAxisExtremum.ts b/packages/x-charts/src/context/CartesianProvider/getAxisExtremum.ts deleted file mode 100644 index 29f9597f571a..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/getAxisExtremum.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { AxisConfig } from '../../models'; -import { CartesianChartSeriesType } from '../../models/seriesType/config'; -import { FormattedSeries } from '../SeriesProvider'; -import { ExtremumGettersConfig, ExtremumGetterResult } from '../PluginProvider'; -import { GetZoomAxisFilters } from './Cartesian.types'; - -const axisExtremumCallback = ( - acc: ExtremumGetterResult, - chartType: T, - axis: AxisConfig, - getters: ExtremumGettersConfig, - axisIndex: number, - formattedSeries: FormattedSeries, - getFilters?: GetZoomAxisFilters, -): ExtremumGetterResult => { - const getter = getters[chartType]; - const series = formattedSeries[chartType]?.series ?? {}; - - const [minChartTypeData, maxChartTypeData] = getter?.({ - series, - axis, - axisIndex, - isDefaultAxis: axisIndex === 0, - getFilters, - }) ?? [Infinity, -Infinity]; - - const [minData, maxData] = acc; - - return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; -}; - -export const getAxisExtremum = ( - axis: AxisConfig, - getters: ExtremumGettersConfig, - axisIndex: number, - formattedSeries: FormattedSeries, - getFilters?: GetZoomAxisFilters, -) => { - const charTypes = Object.keys(getters) as CartesianChartSeriesType[]; - - const extremums = charTypes.reduce( - (acc, charType) => - axisExtremumCallback(acc, charType, axis, getters, axisIndex, formattedSeries, getFilters), - [Infinity, -Infinity], - ); - - if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { - return [Infinity, -Infinity]; - } - - return extremums; -}; diff --git a/packages/x-charts/src/context/CartesianProvider/index.ts b/packages/x-charts/src/context/CartesianProvider/index.ts deleted file mode 100644 index 68ff254ef711..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './CartesianProvider'; -export * from './CartesianContext'; -export * from './useCartesianContext'; -export * from './Cartesian.types'; diff --git a/packages/x-charts/src/context/CartesianProvider/useCartesianContext.ts b/packages/x-charts/src/context/CartesianProvider/useCartesianContext.ts deleted file mode 100644 index afe70ce02e6d..000000000000 --- a/packages/x-charts/src/context/CartesianProvider/useCartesianContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -'use client'; -import * as React from 'react'; -import { CartesianContext } from './CartesianContext'; -import { CartesianContextState } from './Cartesian.types'; - -export const useCartesianContext = (): CartesianContextState => { - const { data } = React.useContext(CartesianContext); - return data; -}; diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 0d1e8efcb256..bc600c86f01b 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -2,23 +2,17 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { MakeOptional } from '@mui/x-internals/types'; -import { SeriesProvider, SeriesProviderProps } from '../SeriesProvider'; -import { CartesianProvider, CartesianProviderProps } from '../CartesianProvider'; -import { PluginProvider, PluginProviderProps } from '../PluginProvider'; import { useChartDataProviderProps } from './useChartDataProviderProps'; import { AxisConfig, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from '../../models/axis'; import { AnimationProvider, AnimationProviderProps } from '../AnimationProvider'; import { ZAxisContextProvider, ZAxisContextProviderProps } from '../ZAxisContextProvider'; import { HighlightedProvider, HighlightedProviderProps } from '../HighlightedProvider'; - import { ChartProvider, ChartProviderProps } from '../ChartProvider'; +import { useChartCartesianAxis } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; export type ChartDataProviderProps = Omit< - Omit & - Pick & - ZAxisContextProviderProps & + ZAxisContextProviderProps & HighlightedProviderProps & - PluginProviderProps & AnimationProviderProps & ChartProviderProps<[]>['pluginParams'], 'children' @@ -68,28 +62,19 @@ export type ChartDataProviderProps = Omit< function ChartDataProvider(props: ChartDataProviderProps) { const { children, - seriesProviderProps, - cartesianProviderProps, zAxisContextProps, highlightedProviderProps, - pluginProviderProps, animationProviderProps, chartProviderProps, } = useChartDataProviderProps(props); return ( - - - - - - - {children} - - - - - + + + + {children} + + ); } diff --git a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts index 3efa74a96c6a..37a1308c3be5 100644 --- a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts +++ b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts @@ -1,13 +1,12 @@ 'use client'; -import type { CartesianProviderProps } from '../CartesianProvider'; -import type { SeriesProviderProps } from '../SeriesProvider'; +import { useTheme } from '@mui/material/styles'; import type { ZAxisContextProviderProps } from '../ZAxisContextProvider'; import type { ChartDataProviderProps } from './ChartDataProvider'; import { HighlightedProviderProps } from '../HighlightedProvider'; import { useDefaultizeAxis } from './useDefaultizeAxis'; -import { PluginProviderProps } from '../PluginProvider'; import { AnimationProviderProps } from '../AnimationProvider'; import { ChartProviderProps } from '../ChartProvider'; +import { UseChartCartesianAxisSignature } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; export const useChartDataProviderProps = (props: ChartDataProviderProps) => { const { @@ -22,19 +21,27 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { dataset, highlightedItem, onHighlightChange, - plugins, children, skipAnimation, } = props; + const theme = useTheme(); const [defaultizedXAxis, defaultizedYAxis] = useDefaultizeAxis(xAxis, yAxis, dataset); - const chartProviderProps: Omit, 'children'> = { - plugins: [], + const chartProviderProps: Omit< + ChartProviderProps<[UseChartCartesianAxisSignature]>, + 'children' + > = { pluginParams: { width, height, margin, + dataset, + series, + colors, + theme: theme.palette.mode, + xAxis: defaultizedXAxis, + yAxis: defaultizedYAxis, }, }; @@ -42,22 +49,6 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { skipAnimation, }; - const pluginProviderProps: Omit = { - plugins, - }; - - const seriesProviderProps: Omit = { - series, - colors, - dataset, - }; - - const cartesianProviderProps: Omit = { - xAxis: defaultizedXAxis, - yAxis: defaultizedYAxis, - dataset, - }; - const zAxisContextProps: Omit = { zAxis, dataset, @@ -70,11 +61,8 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { return { children, - seriesProviderProps, - cartesianProviderProps, zAxisContextProps, highlightedProviderProps, - pluginProviderProps, animationProviderProps, xAxis: defaultizedXAxis, yAxis: defaultizedYAxis, diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx index 1f8d146a90cc..aadba0237c3b 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx @@ -4,13 +4,27 @@ import { useCharts } from '../../internals/store/useCharts'; import { ChartProviderProps } from './ChartProvider.types'; import { ChartContext } from './ChartContext'; import { ChartAnyPluginSignature } from '../../internals/plugins/models'; +import { ChartSeriesConfig } from '../../internals/plugins/models/seriesConfig'; +import { plugin as barPlugin } from '../../BarChart/plugin'; +import { plugin as scatterPlugin } from '../../ScatterChart/plugin'; +import { plugin as linePlugin } from '../../LineChart/plugin'; +import { plugin as piePlugin } from '../../PieChart/plugin'; +import { ChartSeriesType } from '../../models/seriesType/config'; -function ChartProvider( - props: ChartProviderProps, -) { - const { children, plugins = [], pluginParams = {} } = props; +export const defaultSeriesConfig: ChartSeriesConfig<'bar' | 'scatter' | 'line' | 'pie'> = { + bar: barPlugin, + scatter: scatterPlugin, + line: linePlugin, + pie: piePlugin, +}; - const { contextValue } = useCharts(plugins, pluginParams); +function ChartProvider< + TSignatures extends readonly ChartAnyPluginSignature[], + TSeriesType extends ChartSeriesType, +>(props: ChartProviderProps) { + const { children, plugins = [], pluginParams = {}, seriesConfig = defaultSeriesConfig } = props; + + const { contextValue } = useCharts(plugins, pluginParams, seriesConfig); return {children}; } diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index b980c27c4ce1..eb723938d818 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -8,6 +8,8 @@ import { } from '../../internals/plugins/models'; import { ChartStore } from '../../internals/plugins/utils/ChartStore'; import { ChartCorePluginSignatures } from '../../internals/plugins/corePlugins'; +import { ChartSeriesConfig } from '../../internals/plugins/models/seriesConfig'; +import { ChartSeriesType } from '../../models/seriesType/config'; export type ChartContextValue< TSignatures extends readonly ChartAnyPluginSignature[], @@ -31,8 +33,12 @@ export type ChartContextValue< svgRef: React.RefObject; }; -export interface ChartProviderProps { +export interface ChartProviderProps< + TSignatures extends readonly ChartAnyPluginSignature[] = [], + TSeries extends ChartSeriesType = ChartSeriesType, +> { plugins?: ConvertSignaturesIntoPlugins; pluginParams?: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; + seriesConfig?: ChartSeriesConfig; children: React.ReactNode; } diff --git a/packages/x-charts/src/context/PluginProvider/ColorProcessor.types.ts b/packages/x-charts/src/context/PluginProvider/ColorProcessor.types.ts deleted file mode 100644 index d33778d9d556..000000000000 --- a/packages/x-charts/src/context/PluginProvider/ColorProcessor.types.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { AxisDefaultized } from '../../models/axis'; -import type { DefaultizedSeriesType } from '../../models/seriesType'; -import type { ZAxisDefaultized } from '../../models/z-axis'; -import type { ChartSeriesType } from '../../models/seriesType/config'; - -export type ColorProcessor = ( - series: DefaultizedSeriesType, - xAxis?: AxisDefaultized, - yAxis?: AxisDefaultized, - zAxis?: ZAxisDefaultized, -) => (dataIndex: number) => string; - -export type ColorProcessorsConfig = { - [Key in T]?: ColorProcessor; -}; diff --git a/packages/x-charts/src/context/PluginProvider/ExtremumGetter.types.ts b/packages/x-charts/src/context/PluginProvider/ExtremumGetter.types.ts deleted file mode 100644 index 744aa3fd066b..000000000000 --- a/packages/x-charts/src/context/PluginProvider/ExtremumGetter.types.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { - CartesianChartSeriesType, - ChartSeriesDefaultized, - ChartSeriesType, -} from '../../models/seriesType/config'; -import type { AxisConfig, AxisId } from '../../models/axis'; -import type { SeriesId } from '../../models/seriesType/common'; - -export type ExtremumGettersConfig = { - [K in T]?: ExtremumGetter; -}; - -type ExtremumGetterParams = { - series: Record>; - axis: AxisConfig; - axisIndex: number; - isDefaultAxis: boolean; - getFilters?: (params: { - currentAxisId: AxisId | undefined; - seriesXAxisId?: AxisId; - seriesYAxisId?: AxisId; - isDefaultAxis: boolean; - }) => ExtremumFilter; -}; - -export type ExtremumGetterResult = [number, number]; - -export type ExtremumGetter = ( - params: ExtremumGetterParams, -) => ExtremumGetterResult; - -export type ExtremumFilter = ( - value: { x: number | Date | string | null; y: number | Date | string | null }, - dataIndex: number, -) => boolean; diff --git a/packages/x-charts/src/context/PluginProvider/Plugin.types.ts b/packages/x-charts/src/context/PluginProvider/Plugin.types.ts deleted file mode 100644 index 3cc7f7f8826a..000000000000 --- a/packages/x-charts/src/context/PluginProvider/Plugin.types.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { ChartSeriesType } from '../../models/seriesType/config'; -import type { ColorProcessor, ColorProcessorsConfig } from './ColorProcessor.types'; -import type { ExtremumGetter, ExtremumGettersConfig } from './ExtremumGetter.types'; -import type { SeriesFormatter, SeriesFormatterConfig } from './SeriesFormatter.types'; - -export type PluginProviderProps = { - /** - * An array of plugins defining how to preprocess data. - * If not provided, the container supports line, bar, scatter and pie charts. - */ - plugins?: ChartsPlugin[]; - children: React.ReactNode; -}; - -export type PluginContextState = { - seriesFormatters: SeriesFormatterConfig; - colorProcessors: ColorProcessorsConfig; - xExtremumGetters: ExtremumGettersConfig; - yExtremumGetters: ExtremumGettersConfig; - rotationExtremumGetters: ExtremumGettersConfig; - radiusExtremumGetters: ExtremumGettersConfig; -}; - -export type ChartsPlugin = T extends ChartSeriesType - ? { - seriesType: T; - seriesFormatter: SeriesFormatter; - colorProcessor: ColorProcessor; - xExtremumGetter?: ExtremumGetter; - yExtremumGetter?: ExtremumGetter; - rotationExtremumGetter?: ExtremumGetter; - radiusExtremumGetter?: ExtremumGetter; - } - : never; diff --git a/packages/x-charts/src/context/PluginProvider/PluginContext.ts b/packages/x-charts/src/context/PluginProvider/PluginContext.ts deleted file mode 100644 index 3924afa05b79..000000000000 --- a/packages/x-charts/src/context/PluginProvider/PluginContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react'; -import { Initializable } from '../context.types'; -import { PluginContextState } from './Plugin.types'; - -export const PluginContext = React.createContext>({ - isInitialized: false, - data: { - colorProcessors: {}, - seriesFormatters: {}, - xExtremumGetters: {}, - yExtremumGetters: {}, - rotationExtremumGetters: {}, - radiusExtremumGetters: {}, - }, -}); - -if (process.env.NODE_ENV !== 'production') { - PluginContext.displayName = 'PluginContext'; -} diff --git a/packages/x-charts/src/context/PluginProvider/PluginProvider.tsx b/packages/x-charts/src/context/PluginProvider/PluginProvider.tsx deleted file mode 100644 index 891629c7773a..000000000000 --- a/packages/x-charts/src/context/PluginProvider/PluginProvider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -'use client'; -import * as React from 'react'; -import { PluginProviderProps } from './Plugin.types'; -import { PluginContext } from './PluginContext'; -import { mergePlugins } from './mergePlugins'; - -function PluginProvider(props: PluginProviderProps) { - const { children, plugins } = props; - - const formattedSeries = React.useMemo( - () => ({ - isInitialized: true, - data: mergePlugins(plugins), - }), - [plugins], - ); - - return {children}; -} - -export { PluginProvider }; diff --git a/packages/x-charts/src/context/PluginProvider/SeriesFormatter.types.ts b/packages/x-charts/src/context/PluginProvider/SeriesFormatter.types.ts deleted file mode 100644 index 6462da81a53b..000000000000 --- a/packages/x-charts/src/context/PluginProvider/SeriesFormatter.types.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { - ChartSeriesDefaultized, - ChartSeriesType, - ChartsSeriesConfig, - DatasetType, -} from '../../models/seriesType/config'; -import type { SeriesId } from '../../models/seriesType/common'; -import type { StackingGroupsType } from '../../internals/stackSeries'; -import type { LegendItemParams } from '../../ChartsLegend/chartsLegend.types'; - -export type SeriesFormatterParams = { - series: Record; - seriesOrder: SeriesId[]; -}; - -export type SeriesFormatterResult = { - series: Record>; - seriesOrder: SeriesId[]; -} & (ChartsSeriesConfig[T] extends { - canBeStacked: true; -} - ? { stackingGroups: StackingGroupsType } - : {}); - -export type SeriesFormatter = ( - params: SeriesFormatterParams, - dataset?: DatasetType, -) => SeriesFormatterResult; - -export type LegendGetter = ( - series: SeriesFormatterResult, -) => LegendItemParams[]; - -export type SeriesFormatterConfig = { - // TODO replace the function type by Formatter - [K in T]?: (series: SeriesFormatterParams, dataset?: DatasetType) => any; -}; diff --git a/packages/x-charts/src/context/PluginProvider/index.ts b/packages/x-charts/src/context/PluginProvider/index.ts deleted file mode 100644 index 502c2ae75226..000000000000 --- a/packages/x-charts/src/context/PluginProvider/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from './PluginProvider'; -export * from './Plugin.types'; -export * from './PluginContext'; -export * from './ColorProcessor.types'; -export * from './SeriesFormatter.types'; -export * from './ExtremumGetter.types'; -export * from './useColorProcessor'; -export * from './useSeriesFormatter'; -export * from './useXExtremumGetter'; -export * from './useYExtremumGetter'; -export * from './useRadiusExtremumGetter'; -export * from './useRotationExtremumGetter'; diff --git a/packages/x-charts/src/context/PluginProvider/mergePlugins.ts b/packages/x-charts/src/context/PluginProvider/mergePlugins.ts deleted file mode 100644 index 3f4a9338c1a2..000000000000 --- a/packages/x-charts/src/context/PluginProvider/mergePlugins.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { ChartsPlugin } from './Plugin.types'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { SeriesFormatter, SeriesFormatterConfig } from './SeriesFormatter.types'; -import { ColorProcessor, ColorProcessorsConfig } from './ColorProcessor.types'; -import { ExtremumGetter, ExtremumGettersConfig } from './ExtremumGetter.types'; -import { plugin as barPlugin } from '../../BarChart/plugin'; -import { plugin as scatterPlugin } from '../../ScatterChart/plugin'; -import { plugin as linePlugin } from '../../LineChart/plugin'; -import { plugin as piePlugin } from '../../PieChart/plugin'; - -export const defaultPlugins = [barPlugin, scatterPlugin, linePlugin, piePlugin]; - -export function mergePlugins(plugins?: ChartsPlugin[]) { - const defaultizedPlugins = plugins ?? defaultPlugins; - - const seriesFormatters: SeriesFormatterConfig = {}; - const colorProcessors: ColorProcessorsConfig = {}; - const xExtremumGetters: ExtremumGettersConfig = {}; - const yExtremumGetters: ExtremumGettersConfig = {}; - const rotationExtremumGetters: ExtremumGettersConfig = {}; - const radiusExtremumGetters: ExtremumGettersConfig = {}; - - for (let i = 0; i < defaultizedPlugins.length; i += 1) { - const plugin = defaultizedPlugins[i]; - const seriesType = plugin.seriesType; - - seriesFormatters[seriesType] = plugin.seriesFormatter as SeriesFormatter; - - colorProcessors[seriesType] = plugin.colorProcessor as ColorProcessor; - - if (plugin.xExtremumGetter) { - xExtremumGetters[seriesType] = plugin.xExtremumGetter as ExtremumGetter; - } - - if (plugin.yExtremumGetter) { - yExtremumGetters[seriesType] = plugin.yExtremumGetter as ExtremumGetter; - } - - if (plugin.rotationExtremumGetter) { - rotationExtremumGetters[seriesType] = plugin.rotationExtremumGetter as ExtremumGetter< - typeof seriesType - >; - } - if (plugin.radiusExtremumGetter) { - radiusExtremumGetters[seriesType] = plugin.radiusExtremumGetter as ExtremumGetter< - typeof seriesType - >; - } - } - - return { - seriesFormatters, - colorProcessors, - xExtremumGetters, - yExtremumGetters, - rotationExtremumGetters, - radiusExtremumGetters, - }; -} diff --git a/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts b/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts index 2bb5f9ab3de9..e84376b4de38 100644 --- a/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts +++ b/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts @@ -1,28 +1,20 @@ -'use client'; -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { ColorProcessorsConfig } from './ColorProcessor.types'; - -export function useColorProcessor( - seriesType: T, -): ColorProcessorsConfig[T]; -export function useColorProcessor(): ColorProcessorsConfig; -export function useColorProcessor(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.colorProcessors; - } - - return data.colorProcessors[seriesType]; +export function useColorProcessor() { + return { + line: + (..._: any) => + (__?: number) => + 'black', + bar: + (..._: any) => + (__?: number) => + 'black', + scatter: + (..._: any) => + (__?: number) => + 'black', + pie: + (..._: any) => + (__?: number) => + 'black', + }; } diff --git a/packages/x-charts/src/context/PluginProvider/useRadiusExtremumGetter.ts b/packages/x-charts/src/context/PluginProvider/useRadiusExtremumGetter.ts deleted file mode 100644 index bc7e1ce5b56e..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useRadiusExtremumGetter.ts +++ /dev/null @@ -1,28 +0,0 @@ -'use client'; -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { ExtremumGettersConfig } from './ExtremumGetter.types'; - -export function useRadiusExtremumGetter( - seriesType: T, -): ExtremumGettersConfig[T]; -export function useRadiusExtremumGetter(): ExtremumGettersConfig; -export function useRadiusExtremumGetter(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.radiusExtremumGetters; - } - - return data.radiusExtremumGetters[seriesType]; -} diff --git a/packages/x-charts/src/context/PluginProvider/useRotationExtremumGetter.ts b/packages/x-charts/src/context/PluginProvider/useRotationExtremumGetter.ts deleted file mode 100644 index 5b8bc6b92be1..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useRotationExtremumGetter.ts +++ /dev/null @@ -1,28 +0,0 @@ -'use client'; -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { ExtremumGettersConfig } from './ExtremumGetter.types'; - -export function useRotationExtremumGetter( - seriesType: T, -): ExtremumGettersConfig[T]; -export function useRotationExtremumGetter(): ExtremumGettersConfig; -export function useRotationExtremumGetter(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.rotationExtremumGetters; - } - - return data.rotationExtremumGetters[seriesType]; -} diff --git a/packages/x-charts/src/context/PluginProvider/useSeriesFormatter.ts b/packages/x-charts/src/context/PluginProvider/useSeriesFormatter.ts deleted file mode 100644 index 27ed067d6b5d..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useSeriesFormatter.ts +++ /dev/null @@ -1,28 +0,0 @@ -'use client'; -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { SeriesFormatterConfig } from './SeriesFormatter.types'; - -export function useSeriesFormatter( - seriesType: T, -): SeriesFormatterConfig[T]; -export function useSeriesFormatter(): SeriesFormatterConfig; -export function useSeriesFormatter(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.seriesFormatters; - } - - return data.seriesFormatters[seriesType]; -} diff --git a/packages/x-charts/src/context/PluginProvider/useXExtremumGetter.ts b/packages/x-charts/src/context/PluginProvider/useXExtremumGetter.ts deleted file mode 100644 index f9b7f8a80d35..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useXExtremumGetter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { ExtremumGettersConfig } from './ExtremumGetter.types'; - -export function useXExtremumGetter( - seriesType: T, -): ExtremumGettersConfig[T]; -export function useXExtremumGetter(): ExtremumGettersConfig; -export function useXExtremumGetter(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.xExtremumGetters; - } - - return data.xExtremumGetters[seriesType]; -} diff --git a/packages/x-charts/src/context/PluginProvider/useYExtremumGetter.ts b/packages/x-charts/src/context/PluginProvider/useYExtremumGetter.ts deleted file mode 100644 index bc5cd0293223..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useYExtremumGetter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { PluginContext } from './PluginContext'; -import { ExtremumGettersConfig } from './ExtremumGetter.types'; - -export function useYExtremumGetter( - seriesType: T, -): ExtremumGettersConfig[T]; -export function useYExtremumGetter(): ExtremumGettersConfig; -export function useYExtremumGetter(seriesType?: ChartSeriesType) { - const { isInitialized, data } = React.useContext(PluginContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the plugin context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - if (!seriesType) { - return data.yExtremumGetters; - } - - return data.yExtremumGetters[seriesType]; -} diff --git a/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx b/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx index 515e3fa5fbf0..2893ed0d5943 100644 --- a/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx +++ b/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx @@ -1,59 +1,59 @@ -'use client'; -import * as React from 'react'; -import { computeAxisValue } from '../../internals/computeAxisValue'; -import { useDrawingArea } from '../../hooks/useDrawingArea'; -import { useSeries } from '../../hooks/useSeries'; -import { PolarContext } from './PolarContext'; -import { useRadiusExtremumGetter } from '../PluginProvider/useRadiusExtremumGetter'; -import { useRotationExtremumGetter } from '../PluginProvider/useRotationExtremumGetter'; -import { PolarProviderProps } from './Polar.types'; +// 'use client'; +// import * as React from 'react'; +// import { computeAxisValue } from '../../internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue'; +// import { useDrawingArea } from '../../hooks/useDrawingArea'; +// import { useSeries } from '../../hooks/useSeries'; +// import { PolarContext } from './PolarContext'; +// import { useRadiusExtremumGetter } from '../PluginProvider/useRadiusExtremumGetter'; +// import { useRotationExtremumGetter } from '../PluginProvider/useRotationExtremumGetter'; +// import { PolarProviderProps } from './Polar.types'; -function PolarProvider(props: PolarProviderProps) { - const { rotationAxis, radiusAxis, children } = props; +// function PolarProvider(props: PolarProviderProps) { +// const { rotationAxis, radiusAxis, children } = props; - const formattedSeries = useSeries(); - const drawingArea = useDrawingArea(); - const rotationExtremumGetters = useRotationExtremumGetter(); - const radiusExtremumGetters = useRadiusExtremumGetter(); +// const formattedSeries = useSeries(); +// const drawingArea = useDrawingArea(); +// const rotationExtremumGetters = useRotationExtremumGetter(); +// const radiusExtremumGetters = useRadiusExtremumGetter(); - const rotationValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: rotationAxis, - extremumGetters: rotationExtremumGetters, - axisDirection: 'rotation', - }), - [drawingArea, formattedSeries, rotationAxis, rotationExtremumGetters], - ); +// const rotationValues = React.useMemo( +// () => +// computeAxisValue({ +// drawingArea, +// formattedSeries, +// axis: rotationAxis, +// extremumGetters: rotationExtremumGetters, +// axisDirection: 'rotation', +// }), +// [drawingArea, formattedSeries, rotationAxis, rotationExtremumGetters], +// ); - const radiusValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: radiusAxis, - extremumGetters: radiusExtremumGetters, - axisDirection: 'radius', - }), - [drawingArea, formattedSeries, radiusAxis, radiusExtremumGetters], - ); +// const radiusValues = React.useMemo( +// () => +// computeAxisValue({ +// drawingArea, +// formattedSeries, +// axis: radiusAxis, +// extremumGetters: radiusExtremumGetters, +// axisDirection: 'radius', +// }), +// [drawingArea, formattedSeries, radiusAxis, radiusExtremumGetters], +// ); - const value = React.useMemo( - () => ({ - isInitialized: true, - data: { - rotationAxis: rotationValues.axis, - radiusAxis: radiusValues.axis, - rotationAxisIds: rotationValues.axisIds, - radiusAxisIds: radiusValues.axisIds, - }, - }), - [rotationValues, radiusValues], - ); +// const value = React.useMemo( +// () => ({ +// isInitialized: true, +// data: { +// rotationAxis: rotationValues.axis, +// radiusAxis: radiusValues.axis, +// rotationAxisIds: rotationValues.axisIds, +// radiusAxisIds: radiusValues.axisIds, +// }, +// }), +// [rotationValues, radiusValues], +// ); - return {children}; -} +// return {children}; +// } -export { PolarProvider }; +// export { PolarProvider }; diff --git a/packages/x-charts/src/context/PolarProvider/getAxisExtremum.ts b/packages/x-charts/src/context/PolarProvider/getAxisExtremum.ts index e08b66fab04e..ce09ab3fc1e1 100644 --- a/packages/x-charts/src/context/PolarProvider/getAxisExtremum.ts +++ b/packages/x-charts/src/context/PolarProvider/getAxisExtremum.ts @@ -1,48 +1,48 @@ -import { AxisConfig } from '../../models'; -import { CartesianChartSeriesType } from '../../models/seriesType/config'; -import { FormattedSeries } from '../SeriesProvider'; -import { ExtremumGettersConfig, ExtremumGetterResult } from '../PluginProvider'; - -const axisExtremumCallback = ( - acc: ExtremumGetterResult, - chartType: T, - axis: AxisConfig, - getters: ExtremumGettersConfig, - axisIndex: number, - formattedSeries: FormattedSeries, -): ExtremumGetterResult => { - const getter = getters[chartType]; - const series = formattedSeries[chartType]?.series ?? {}; - - const [minChartTypeData, maxChartTypeData] = getter?.({ - series, - axis, - axisIndex, - isDefaultAxis: axisIndex === 0, - }) ?? [Infinity, -Infinity]; - - const [minData, maxData] = acc; - - return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; -}; - -export const getAxisExtremum = ( - axis: AxisConfig, - getters: ExtremumGettersConfig, - axisIndex: number, - formattedSeries: FormattedSeries, -) => { - const charTypes = Object.keys(getters) as CartesianChartSeriesType[]; - - const extremums = charTypes.reduce( - (acc, charType) => - axisExtremumCallback(acc, charType, axis, getters, axisIndex, formattedSeries), - [Infinity, -Infinity], - ); - - if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { - return [Infinity, -Infinity]; - } - - return extremums; -}; +// import { AxisConfig } from '../../models'; +// import { CartesianChartSeriesType } from '../../models/seriesType/config'; +// import { FormattedSeries } from '../SeriesProvider'; +// import { ExtremumGettersConfig, ExtremumGetterResult } from '../PluginProvider'; + +// const axisExtremumCallback = ( +// acc: ExtremumGetterResult, +// chartType: T, +// axis: AxisConfig, +// getters: ExtremumGettersConfig, +// axisIndex: number, +// formattedSeries: FormattedSeries, +// ): ExtremumGetterResult => { +// const getter = getters[chartType]; +// const series = formattedSeries[chartType]?.series ?? {}; + +// const [minChartTypeData, maxChartTypeData] = getter?.({ +// series, +// axis, +// axisIndex, +// isDefaultAxis: axisIndex === 0, +// }) ?? [Infinity, -Infinity]; + +// const [minData, maxData] = acc; + +// return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; +// }; + +// export const getAxisExtremum = ( +// axis: AxisConfig, +// getters: ExtremumGettersConfig, +// axisIndex: number, +// formattedSeries: FormattedSeries, +// ) => { +// const charTypes = Object.keys(getters) as CartesianChartSeriesType[]; + +// const extremums = charTypes.reduce( +// (acc, charType) => +// axisExtremumCallback(acc, charType, axis, getters, axisIndex, formattedSeries), +// [Infinity, -Infinity], +// ); + +// if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { +// return [Infinity, -Infinity]; +// } + +// return extremums; +// }; diff --git a/packages/x-charts/src/context/PolarProvider/usePolarContext.ts b/packages/x-charts/src/context/PolarProvider/usePolarContext.ts index 7973cc6a535a..bd849000ea6f 100644 --- a/packages/x-charts/src/context/PolarProvider/usePolarContext.ts +++ b/packages/x-charts/src/context/PolarProvider/usePolarContext.ts @@ -1,9 +1,9 @@ -'use client'; -import * as React from 'react'; -import { PolarContext } from './PolarContext'; -import { PolarContextState } from './Polar.types'; +// 'use client'; +// import * as React from 'react'; +// import { PolarContext } from './PolarContext'; +// import { PolarContextState } from './Polar.types'; -export const usePolarContext = (): PolarContextState => { - const { data } = React.useContext(PolarContext); - return data; -}; +// export const usePolarContext = (): PolarContextState => { +// const { data } = React.useContext(PolarContext); +// return data; +// }; diff --git a/packages/x-charts/src/context/SeriesProvider/Series.types.ts b/packages/x-charts/src/context/SeriesProvider/Series.types.ts deleted file mode 100644 index bdf501919690..000000000000 --- a/packages/x-charts/src/context/SeriesProvider/Series.types.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as React from 'react'; -import { AllSeriesType } from '../../models/seriesType'; -import { ChartSeriesType, DatasetType } from '../../models/seriesType/config'; -import { ChartsColorPalette } from '../../colorPalettes'; -import { SeriesFormatterResult } from '../PluginProvider'; - -export type SeriesFormatterType = ( - series: AllSeriesType[], - colors: string[], - dataset?: DatasetType, -) => { [type in T]?: SeriesFormatterResult }; - -export type SeriesProviderProps = { - dataset?: DatasetType; - /** - * The array of series to display. - * Each type of series has its own specificity. - * Please refer to the appropriate docs page to learn more about it. - */ - series: AllSeriesType[]; - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors?: ChartsColorPalette; - children: React.ReactNode; -}; - -export type FormattedSeries = { [type in ChartSeriesType]?: SeriesFormatterResult }; diff --git a/packages/x-charts/src/context/SeriesProvider/SeriesContext.ts b/packages/x-charts/src/context/SeriesProvider/SeriesContext.ts deleted file mode 100644 index 712d5bdb6e0c..000000000000 --- a/packages/x-charts/src/context/SeriesProvider/SeriesContext.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as React from 'react'; -import { Initializable } from '../context.types'; -import { FormattedSeries } from './Series.types'; - -export const SeriesContext = React.createContext>({ - isInitialized: false, - data: {}, -}); - -if (process.env.NODE_ENV !== 'production') { - SeriesContext.displayName = 'SeriesContext'; -} diff --git a/packages/x-charts/src/context/SeriesProvider/SeriesProvider.tsx b/packages/x-charts/src/context/SeriesProvider/SeriesProvider.tsx deleted file mode 100644 index 9a37c692b45c..000000000000 --- a/packages/x-charts/src/context/SeriesProvider/SeriesProvider.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'use client'; -import * as React from 'react'; -import { useTheme } from '@mui/material/styles'; -import { ChartSeriesType, DatasetType } from '../../models/seriesType/config'; -import { blueberryTwilightPalette } from '../../colorPalettes'; -import { SeriesProviderProps } from './Series.types'; -import { SeriesContext } from './SeriesContext'; -import { preprocessSeries } from './processSeries'; -import { useSeriesFormatter } from '../PluginProvider'; - -function SeriesProvider(props: SeriesProviderProps) { - const { series, dataset, colors = blueberryTwilightPalette, children } = props; - - const seriesFormatters = useSeriesFormatter(); - - const theme = useTheme(); - - const formattedSeries = React.useMemo( - () => ({ - isInitialized: true, - data: preprocessSeries({ - series, - colors: typeof colors === 'function' ? colors(theme.palette.mode) : colors, - seriesFormatters, - dataset: dataset as DatasetType, - }), - }), - [series, colors, theme.palette.mode, seriesFormatters, dataset], - ); - - return {children}; -} - -export { SeriesProvider }; diff --git a/packages/x-charts/src/context/SeriesProvider/index.ts b/packages/x-charts/src/context/SeriesProvider/index.ts deleted file mode 100644 index 852fb6928868..000000000000 --- a/packages/x-charts/src/context/SeriesProvider/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { preprocessSeries } from './processSeries'; - -export * from './SeriesProvider'; -export * from './SeriesContext'; -export * from './Series.types'; - -const seriesProviderUtils = { - preprocessSeries, -}; - -export { seriesProviderUtils }; diff --git a/packages/x-charts/src/context/SeriesProvider/processSeries.ts b/packages/x-charts/src/context/SeriesProvider/processSeries.ts deleted file mode 100644 index de2ce7fff482..000000000000 --- a/packages/x-charts/src/context/SeriesProvider/processSeries.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { AllSeriesType } from '../../models/seriesType'; -import { defaultizeColor } from '../../internals/defaultizeColor'; -import { ChartSeriesType, DatasetType } from '../../models/seriesType/config'; -import { FormattedSeries } from './Series.types'; -import { SeriesFormatterConfig, SeriesFormatterParams } from '../PluginProvider'; - -/** - * This methods is the interface between what the developer is providing and what components receives - * To simplify the components behaviors, it groups series by type, such that LinePlots props are not updated if some line data are modified - * It also add defaultized values such as the ids, colors - * @param series The array of series provided by the developer - * @param colors The color palette used to defaultize series colors - * @returns An object structuring all the series by type. - */ -export const preprocessSeries = ({ - series, - colors, - seriesFormatters, - dataset, -}: { - series: AllSeriesType[]; - colors: string[]; - seriesFormatters: SeriesFormatterConfig; - dataset?: DatasetType; -}) => { - // Group series by type - const seriesGroups: { [type in ChartSeriesType]?: SeriesFormatterParams } = {}; - series.forEach((seriesData, seriesIndex: number) => { - const { id = `auto-generated-id-${seriesIndex}`, type } = seriesData; - - if (seriesGroups[type] === undefined) { - seriesGroups[type] = { series: {}, seriesOrder: [] }; - } - if (seriesGroups[type]?.series[id] !== undefined) { - throw new Error(`MUI X: series' id "${id}" is not unique.`); - } - - seriesGroups[type]!.series[id] = { - id, - ...defaultizeColor(seriesData, seriesIndex, colors), - }; - seriesGroups[type]!.seriesOrder.push(id); - }); - - const formattedSeries: FormattedSeries = {}; - // Apply formatter on a type group - (Object.keys(seriesFormatters) as T[]).forEach((type) => { - const group = seriesGroups[type]; - if (group !== undefined) { - formattedSeries[type] = seriesFormatters[type]?.(group, dataset) ?? seriesGroups[type]; - } - }); - - return formattedSeries; -}; diff --git a/packages/x-charts/src/hooks/useAxis.ts b/packages/x-charts/src/hooks/useAxis.ts index 7f4ac25f6cef..3e036c4b06a2 100644 --- a/packages/x-charts/src/hooks/useAxis.ts +++ b/packages/x-charts/src/hooks/useAxis.ts @@ -1,8 +1,29 @@ 'use client'; -import { useCartesianContext } from '../context/CartesianProvider'; +import { UseChartCartesianAxisSignature } from '../internals/plugins/featurePlugins/useChartCartesianAxis'; +import { + selectorChartXAxis, + selectorChartYAxis, +} from '../internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors'; +import { useSelector } from '../internals/store/useSelector'; +import { useStore } from '../internals/store/useStore'; + +export function useXAxes() { + const store = useStore<[UseChartCartesianAxisSignature]>(); + const { axis: xAxis, axisIds: xAxisIds } = useSelector(store, selectorChartXAxis); + + return { xAxis, xAxisIds }; +} + +export function useYAxes() { + const store = useStore<[UseChartCartesianAxisSignature]>(); + const { axis: yAxis, axisIds: yAxisIds } = useSelector(store, selectorChartYAxis); + + return { yAxis, yAxisIds }; +} export function useXAxis(identifier?: number | string) { - const { xAxis, xAxisIds } = useCartesianContext(); + const store = useStore<[UseChartCartesianAxisSignature]>(); + const { axis: xAxis, axisIds: xAxisIds } = useSelector(store, selectorChartXAxis); const id = typeof identifier === 'string' ? identifier : xAxisIds[identifier ?? 0]; @@ -10,7 +31,8 @@ export function useXAxis(identifier?: number | string) { } export function useYAxis(identifier?: number | string) { - const { yAxis, yAxisIds } = useCartesianContext(); + const store = useStore<[UseChartCartesianAxisSignature]>(); + const { axis: yAxis, axisIds: yAxisIds } = useSelector(store, selectorChartYAxis); const id = typeof identifier === 'string' ? identifier : yAxisIds[identifier ?? 0]; diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index b2bbc157e998..f9638eb0a70d 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -1,12 +1,12 @@ 'use client'; import * as React from 'react'; -import { useCartesianContext } from '../context/CartesianProvider'; import { isBandScale } from '../internals/isBandScale'; import { AxisDefaultized } from '../models/axis'; import { getSVGPoint } from '../internals/getSVGPoint'; import { useSvgRef } from './useSvgRef'; import { useStore } from '../internals/store/useStore'; import { useChartContext } from '../context/ChartProvider'; +import { useXAxes, useYAxes } from './useAxis'; function getAsANumber(value: number | Date) { return value instanceof Date ? value.getTime() : value; @@ -14,7 +14,8 @@ function getAsANumber(value: number | Date) { export const useAxisEvents = (disableAxisListener: boolean) => { const svgRef = useSvgRef(); const { instance } = useChartContext(); - const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const store = useStore(disableAxisListener); diff --git a/packages/x-charts/src/hooks/useColorScale.ts b/packages/x-charts/src/hooks/useColorScale.ts index f4284efa7454..dbdf074925a5 100644 --- a/packages/x-charts/src/hooks/useColorScale.ts +++ b/packages/x-charts/src/hooks/useColorScale.ts @@ -1,13 +1,13 @@ 'use client'; import * as React from 'react'; -import { useCartesianContext } from '../context/CartesianProvider'; import { AxisScaleComputedConfig, ScaleName } from '../models/axis'; import { ZAxisContext } from '../context/ZAxisContextProvider'; +import { useXAxes, useYAxes } from './useAxis'; export function useXColorScale( identifier?: number | string, ): AxisScaleComputedConfig[S]['colorScale'] | undefined { - const { xAxis, xAxisIds } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); const id = typeof identifier === 'string' ? identifier : xAxisIds[identifier ?? 0]; @@ -17,7 +17,7 @@ export function useXColorScale( export function useYColorScale( identifier?: number | string, ): AxisScaleComputedConfig[S]['colorScale'] | undefined { - const { yAxis, yAxisIds } = useCartesianContext(); + const { yAxis, yAxisIds } = useYAxes(); const id = typeof identifier === 'string' ? identifier : yAxisIds[identifier ?? 0]; diff --git a/packages/x-charts/src/hooks/useSeries.test.tsx b/packages/x-charts/src/hooks/useSeries.test.tsx index 8bc52cb6c2e3..eb0c562c05cd 100644 --- a/packages/x-charts/src/hooks/useSeries.test.tsx +++ b/packages/x-charts/src/hooks/useSeries.test.tsx @@ -2,8 +2,6 @@ import * as React from 'react'; import { expect } from 'chai'; import { ErrorBoundary, createRenderer, reactMajor, screen } from '@mui/internal-test-utils'; import { useSeries } from './useSeries'; -import { SeriesProvider } from '../context/SeriesProvider'; -import { PluginProvider } from '../internals'; function UseSeries() { const { bar } = useSeries(); @@ -47,11 +45,11 @@ describe('useSeries', () => { it('should not throw an error when parent context is present', () => { render( - - - - - , + // + // + , + // + // , ); expect(screen.getByText('test-id')).toBeVisible(); diff --git a/packages/x-charts/src/hooks/useSeries.ts b/packages/x-charts/src/hooks/useSeries.ts index 4f68bfa6ef1e..38fb374e64c9 100644 --- a/packages/x-charts/src/hooks/useSeries.ts +++ b/packages/x-charts/src/hooks/useSeries.ts @@ -1,6 +1,9 @@ 'use client'; import * as React from 'react'; -import { FormattedSeries, SeriesContext } from '../context/SeriesProvider'; +import { useStore } from '../internals/store/useStore'; +import { useSelector } from '../internals/store/useSelector'; +import { selectorChartSeriesState } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors'; +import { UseChartSeriesSignature } from '../internals/plugins/corePlugins/useChartSeries'; /** * Get access to the internal state of series. @@ -8,19 +11,9 @@ import { FormattedSeries, SeriesContext } from '../context/SeriesProvider'; * { seriesType?: { series: { id1: precessedValue, ... }, seriesOrder: [id1, ...] } } * @returns FormattedSeries series */ -export function useSeries(): FormattedSeries { - const { isInitialized, data } = React.useContext(SeriesContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the series ref context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - return data; +export function useSeries() { + const store = useStore<[UseChartSeriesSignature]>(); + return useSelector(store, selectorChartSeriesState); } /** @@ -30,7 +23,7 @@ export function useSeries(): FormattedSeries { * - seriesOrder: the array of series ids. * @returns {{ series: Record; seriesOrder: SeriesId[]; } | undefined} pieSeries */ -export function usePieSeries(): FormattedSeries['pie'] { +export function usePieSeries() { const series = useSeries(); return React.useMemo(() => series.pie, [series.pie]); @@ -43,7 +36,7 @@ export function usePieSeries(): FormattedSeries['pie'] { * - seriesOrder: the array of series ids. * @returns {{ series: Record; seriesOrder: SeriesId[]; } | undefined} lineSeries */ -export function useLineSeries(): FormattedSeries['line'] { +export function useLineSeries() { const series = useSeries(); return React.useMemo(() => series.line, [series.line]); @@ -56,7 +49,7 @@ export function useLineSeries(): FormattedSeries['line'] { * - seriesOrder: the array of series ids. * @returns {{ series: Record; seriesOrder: SeriesId[]; } | undefined} barSeries */ -export function useBarSeries(): FormattedSeries['bar'] { +export function useBarSeries() { const series = useSeries(); return React.useMemo(() => series.bar, [series.bar]); @@ -69,7 +62,7 @@ export function useBarSeries(): FormattedSeries['bar'] { * - seriesOrder: the array of series ids. * @returns {{ series: Record; seriesOrder: SeriesId[]; } | undefined} scatterSeries */ -export function useScatterSeries(): FormattedSeries['scatter'] { +export function useScatterSeries() { const series = useSeries(); return React.useMemo(() => series.scatter, [series.scatter]); diff --git a/packages/x-charts/src/internals/components/ChartsAxesGradients/ChartsAxesGradients.tsx b/packages/x-charts/src/internals/components/ChartsAxesGradients/ChartsAxesGradients.tsx index 7443e5754dc5..f047f2586453 100644 --- a/packages/x-charts/src/internals/components/ChartsAxesGradients/ChartsAxesGradients.tsx +++ b/packages/x-charts/src/internals/components/ChartsAxesGradients/ChartsAxesGradients.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; -import { useCartesianContext } from '../../../context/CartesianProvider'; -import { useChartId, useDrawingArea } from '../../../hooks'; +import { useChartId, useDrawingArea, useXAxes, useYAxes } from '../../../hooks'; import ChartsPiecewiseGradient from './ChartsPiecewiseGradient'; import ChartsContinuousGradient from './ChartsContinuousGradient'; import { AxisId } from '../../../models/axis'; @@ -19,7 +18,8 @@ export function ChartsAxesGradients() { const svgHeight = top + height + bottom; const svgWidth = left + width + right; const getGradientId = useChartGradient(); - const { xAxisIds, xAxis, yAxisIds, yAxis } = useCartesianContext(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const filteredYAxisIds = yAxisIds.filter((axisId) => yAxis[axisId].colorMap !== undefined); const filteredXAxisIds = xAxisIds.filter((axisId) => xAxis[axisId].colorMap !== undefined); diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index ad19de6775b9..fda48ee8a263 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -19,17 +19,14 @@ export * from './getSVGPoint'; export * from './isDefined'; export { unstable_cleanupDOM } from './domUtils'; export * from './getScale'; -export * from './computeAxisValue'; +export * from './plugins/featurePlugins/useChartCartesianAxis/computeAxisValue'; // contexts -export * from '../context/CartesianProvider'; -export * from '../context/SeriesProvider'; export * from '../context/ZAxisContextProvider'; -export * from '../context/PluginProvider'; export * from '../context/AnimationProvider'; export type * from '../context/context.types'; -export { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum'; +export { getAxisExtremum } from './plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum'; export * from '../context/ChartDataProvider'; export * from '../context/ChartProvider'; @@ -39,3 +36,5 @@ export * from '../models/seriesType/common'; export * from '../models/z-axis'; export * from '../models/axis'; + +export * from './plugins/models'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts b/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts index 3f08d4150ede..8b876ac4b66a 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts @@ -1,12 +1,13 @@ import { ConvertPluginsIntoSignatures } from '../models/helpers'; import { useChartDimensions } from './useChartDimensions/useChartDimensions'; import { useChartId, UseChartIdParameters } from './useChartId'; +import { useChartSeries } from './useChartSeries'; /** * Internal plugins that create the tools used by the other plugins. * These plugins are used by the Charts components. */ -export const CHART_CORE_PLUGINS = [useChartId, useChartDimensions] as const; +export const CHART_CORE_PLUGINS = [useChartId, useChartDimensions, useChartSeries] as const; export type ChartCorePluginSignatures = ConvertPluginsIntoSignatures; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts index bdd0f65b2021..e84d650eea36 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts @@ -24,5 +24,5 @@ useChartId.params = { }; useChartId.getInitialState = ({ id }) => ({ - id: { chartId: createChartDefaultId(), providedChartId: id }, + id: { chartId: undefined, providedChartId: id }, }); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts index 99df1544ece6..77a16098f6b4 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts @@ -12,7 +12,7 @@ export type UseChartIdDefaultizedParameters = UseChartIdParameters; export interface UseChartIdState { id: { - chartId: string; + chartId: string | undefined; providedChartId: string | undefined; }; } diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts new file mode 100644 index 000000000000..c2a75681bb0d --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts @@ -0,0 +1,6 @@ +export { useChartSeries } from './useChartSeries'; +export type { + UseChartSeriesSignature, + UseChartSeriesParameters, + UseChartSeriesDefaultizedParameters, +} from './useChartSeries.types'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/processSeries.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/processSeries.ts new file mode 100644 index 000000000000..3212c8f5d79b --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/processSeries.ts @@ -0,0 +1,63 @@ +import { AllSeriesType } from '../../../../models/seriesType'; +import { defaultizeColor } from '../../../defaultizeColor'; +import { ChartSeriesType, DatasetType } from '../../../../models/seriesType/config'; +import { ChartSeriesConfig } from '../../models/seriesConfig'; +import { + SeriesProcessorParams, + SeriesProcessorResult, +} from '../../models/seriesConfig/seriesProcessor.types'; + +/** + * This methods is the interface between what the developer is providing and what components receives + * To simplify the components behaviors, it groups series by type, such that LinePlots props are not updated if some line data are modified + * It also add defaultized values such as the ids, colors + * @param series The array of series provided by the developer + * @param colors The color palette used to defaultize series colors + * @returns An object structuring all the series by type. + */ +export const preprocessSeries = ({ + series, + colors, + seriesConfig, + dataset, +}: { + series: AllSeriesType[]; + colors: string[]; + seriesConfig: ChartSeriesConfig; + dataset?: DatasetType; +}) => { + // Group series by type + const seriesGroups: { [type in ChartSeriesType]?: SeriesProcessorParams } = {}; + // Notice the line about uses `ChartSeriesType` instead of TSeriesType. + // That's probably because the series.type is not propagated from the generic but hardcoded in the config. + + series.forEach((seriesData, seriesIndex: number) => { + const { id = `auto-generated-id-${seriesIndex}`, type } = + seriesData as AllSeriesType; + + if (seriesGroups[type] === undefined) { + seriesGroups[type] = { series: {}, seriesOrder: [] }; + } + if (seriesGroups[type]?.series[id] !== undefined) { + throw new Error(`MUI X: series' id "${id}" is not unique.`); + } + + seriesGroups[type]!.series[id] = { + id, + ...defaultizeColor(seriesData, seriesIndex, colors), + }; + seriesGroups[type]!.seriesOrder.push(id); + }); + + const processedSeries: { [type in TSeriesType]?: SeriesProcessorResult } = {}; + // Apply formatter on a type group + (Object.keys(seriesConfig) as TSeriesType[]).forEach((type) => { + const group = seriesGroups[type]; + if (group !== undefined) { + processedSeries[type] = + seriesConfig[type]?.seriesProcessor?.(group, dataset) ?? seriesGroups[type]; + } + }); + + return processedSeries; +}; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts new file mode 100644 index 000000000000..9e8262fd7ed0 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts @@ -0,0 +1,5 @@ +import { ChartRootSelector } from '../../utils/selectors'; +import { UseChartSeriesSignature } from './useChartSeries.types'; + +export const selectorChartSeriesState: ChartRootSelector = (state) => + state.series; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts new file mode 100644 index 000000000000..97394dd86aa5 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts @@ -0,0 +1,52 @@ +'use client'; +import * as React from 'react'; +import { ChartPlugin } from '../../models'; +import { UseChartSeriesSignature } from './useChartSeries.types'; +import { blueberryTwilightPalette } from '../../../../colorPalettes'; +import { preprocessSeries } from './processSeries'; + +export const useChartSeries: ChartPlugin = ({ + params, + store, + seriesConfig, +}) => { + const { series = [], dataset, theme, colors } = params; + + React.useEffect(() => { + store.update((prev) => ({ + ...prev, + series: preprocessSeries({ + series, + colors: typeof colors === 'function' ? colors(theme) : colors, + seriesConfig, + dataset, + }), + })); + }, [colors, dataset, series, theme, seriesConfig, store]); + + return {}; +}; + +useChartSeries.params = { + dataset: true, + series: true, + colors: true, + theme: true, +}; + +useChartSeries.getDefaultizedParams = ({ params }) => ({ + ...params, + colors: params.colors ?? blueberryTwilightPalette, + theme: params.theme ?? 'light', +}); + +useChartSeries.getInitialState = ({ series = [], colors, theme, dataset }, _, seriesConfig) => { + return { + series: preprocessSeries({ + series, + colors: typeof colors === 'function' ? colors(theme) : colors, + seriesConfig, + dataset, + }), + }; +}; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts new file mode 100644 index 000000000000..ff9305ed6966 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts @@ -0,0 +1,54 @@ +import { AllSeriesType } from '../../../../models/seriesType'; +import { ChartsColorPalette } from '../../../../colorPalettes'; +import { ChartPluginSignature } from '../../models'; +import { ChartSeriesType, DatasetType } from '../../../../models/seriesType/config'; +import { SeriesProcessorResult } from '../../models/seriesConfig/seriesProcessor.types'; + +export interface UseChartSeriesParameters { + dataset?: DatasetType; + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series?: AllSeriesType[]; + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors?: ChartsColorPalette; + theme?: 'light' | 'dark'; +} + +export type UseChartSeriesDefaultizedParameters = + UseChartSeriesParameters & { + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series?: AllSeriesType[]; + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: ChartsColorPalette; + theme: 'light' | 'dark'; + }; + +export type ProcessedSeries = { + [type in TSeriesTypes]?: SeriesProcessorResult; +}; + +export interface UseChartSeriesState { + series: ProcessedSeries; +} + +export interface UseChartSeriesInstance {} + +export type UseChartSeriesSignature = ChartPluginSignature<{ + params: UseChartSeriesParameters; + defaultizedParams: UseChartSeriesDefaultizedParameters; + state: UseChartSeriesState; + instance: UseChartSeriesInstance; +}>; diff --git a/packages/x-charts/src/internals/computeAxisValue.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts similarity index 74% rename from packages/x-charts/src/internals/computeAxisValue.ts rename to packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts index 6c7d27026e3d..3e9d5017fa36 100644 --- a/packages/x-charts/src/internals/computeAxisValue.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts @@ -1,55 +1,53 @@ import { scaleBand, scalePoint, scaleTime } from '@mui/x-charts-vendor/d3-scale'; -import { AxisConfig, ScaleName } from '../models'; +import { AxisConfig, ScaleName } from '../../../../models'; import { ChartsXAxisProps, ChartsAxisProps, ChartsYAxisProps, isBandScaleConfig, isPointScaleConfig, - ChartsRadiusAxisProps, - ChartsRotationAxisProps, -} from '../models/axis'; -import { CartesianChartSeriesType } from '../models/seriesType/config'; -import { getColorScale, getOrdinalColorScale } from './colorScale'; -import { getTickNumber } from '../hooks/useTicks'; -import { getScale } from './getScale'; - -import { FormattedSeries } from '../context/SeriesProvider'; -import { zoomScaleRange } from '../context/CartesianProvider/zoom'; -import { ExtremumGetter } from '../context/PluginProvider'; +} from '../../../../models/axis'; +import { ChartSeriesType } from '../../../../models/seriesType/config'; +import { getColorScale, getOrdinalColorScale } from '../../../colorScale'; +import { getTickNumber } from '../../../../hooks/useTicks'; +import { getScale } from '../../../getScale'; +import { zoomScaleRange } from './zoom'; +import { getAxisExtremum } from './getAxisExtremum'; +import type { ChartDrawingArea } from '../../../../hooks'; +import { ChartSeriesConfig } from '../../models/seriesConfig'; import { DefaultizedAxisConfig, + GetZoomAxisFilters, ZoomData, ZoomOptions, - GetZoomAxisFilters, -} from '../context/CartesianProvider/Cartesian.types'; -import { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum'; -import type { ChartDrawingArea } from '../hooks'; +} from './useChartCartesianAxis.types'; +import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; function getRange( drawingArea: ChartDrawingArea, - axisDirection: 'x' | 'y' | 'radius' | 'rotation', + axisDirection: 'x' | 'y', // | 'rotation' | 'radius', axis: AxisConfig< ScaleName, any, - ChartsRotationAxisProps | ChartsRotationAxisProps | ChartsAxisProps + // ChartsRotationAxisProps | ChartsRotationAxisProps | + ChartsAxisProps >, ): [number, number] { - if (axisDirection === 'rotation') { - const { startAngle = 0, endAngle = startAngle + 360 } = axis as AxisConfig< - ScaleName, - any, - ChartsRotationAxisProps - >; - return axis.reverse - ? [(Math.PI * startAngle) / 180, (Math.PI * endAngle) / 180] - : [(Math.PI * endAngle) / 180, (Math.PI * startAngle) / 180]; - } - if (axisDirection === 'radius') { - const { minRadius = 0, maxRadius = Math.min(drawingArea.width, drawingArea.height) / 2 } = - axis as AxisConfig; - return [minRadius, maxRadius]; - } + // if (axisDirection === 'rotation') { + // const { startAngle = 0, endAngle = startAngle + 360 } = axis as AxisConfig< + // ScaleName, + // any, + // ChartsRotationAxisProps + // >; + // return axis.reverse + // ? [(Math.PI * startAngle) / 180, (Math.PI * endAngle) / 180] + // : [(Math.PI * endAngle) / 180, (Math.PI * startAngle) / 180]; + // } + // if (axisDirection === 'radius') { + // const { minRadius = 0, maxRadius = Math.min(drawingArea.width, drawingArea.height) / 2 } = + // axis as AxisConfig; + // return [minRadius, maxRadius]; + // } const range: [number, number] = axisDirection === 'x' @@ -81,8 +79,8 @@ type ComputeResult = { type ComputeCommonParams = { drawingArea: ChartDrawingArea; - formattedSeries: FormattedSeries; - extremumGetters: { [K in CartesianChartSeriesType]?: ExtremumGetter }; + formattedSeries: ProcessedSeries; + seriesConfig: ChartSeriesConfig; zoomData?: ZoomData[]; zoomOptions?: ZoomOptions; getFilters?: GetZoomAxisFilters; @@ -100,30 +98,30 @@ export function computeAxisValue( axisDirection: 'x'; }, ): ComputeResult; -export function computeAxisValue( - options: ComputeCommonParams & { - axis: AxisConfig[]; - axisDirection: 'radius'; - }, -): ComputeResult; -export function computeAxisValue( - options: ComputeCommonParams & { - axis: AxisConfig[]; - axisDirection: 'rotation'; - }, -): ComputeResult; +// export function computeAxisValue( +// options: ComputeCommonParams & { +// axis: AxisConfig[]; +// axisDirection: 'radius'; +// }, +// ): ComputeResult; +// export function computeAxisValue( +// options: ComputeCommonParams & { +// axis: AxisConfig[]; +// axisDirection: 'rotation'; +// }, +// ): ComputeResult; export function computeAxisValue({ drawingArea, formattedSeries, axis: allAxis, - extremumGetters, + seriesConfig, axisDirection, zoomData, zoomOptions, getFilters, }: ComputeCommonParams & { axis: AxisConfig[]; - axisDirection: 'x' | 'y' | 'radius' | 'rotation'; + axisDirection: 'x' | 'y'; // | 'radius' | 'rotation'; }) { const completeAxis: DefaultizedAxisConfig = {}; allAxis.forEach((eachAxis, axisIndex) => { @@ -135,7 +133,8 @@ export function computeAxisValue({ const [minData, maxData] = getAxisExtremum( axis, - extremumGetters, + axisDirection, + seriesConfig, axisIndex, formattedSeries, zoom === undefined && !zoomOption ? getFilters : undefined, // Do not apply filtering if zoom is already defined. diff --git a/packages/x-charts/src/context/CartesianProvider/defaultizeAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts similarity index 74% rename from packages/x-charts/src/context/CartesianProvider/defaultizeAxis.ts rename to packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts index 0ae491cce71d..6a357388a6cd 100644 --- a/packages/x-charts/src/context/CartesianProvider/defaultizeAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts @@ -1,7 +1,7 @@ import { MakeOptional } from '@mui/x-internals/types'; -import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../../constants'; -import { AxisConfig, ScaleName } from '../../models'; -import { ChartsAxisProps } from '../../models/axis'; +import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../../../../constants'; +import { AxisConfig, ScaleName } from '../../../../models'; +import { ChartsAxisProps } from '../../../../models/axis'; export const defaultizeAxis = ( inAxis: MakeOptional, 'id'>[] | undefined, diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts new file mode 100644 index 000000000000..bc8536f0e71d --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts @@ -0,0 +1,67 @@ +import { AxisConfig } from '../../../../models'; +import { CartesianChartSeriesType } from '../../../../models/seriesType/config'; +import { ChartSeriesConfig } from '../../models/seriesConfig'; +import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; +import { CartesianExtremumGetter } from '../../models/seriesConfig/extremumGetter.types'; +import { ExtremumGetterResult, GetZoomAxisFilters } from './useChartCartesianAxis.types'; + +const axisExtremumCallback = ( + acc: ExtremumGetterResult, + chartType: TSeriesType, + axis: AxisConfig, + axisDirection: 'x' | 'y', + seriesConfig: ChartSeriesConfig, + axisIndex: number, + formattedSeries: ProcessedSeries, + getFilters?: GetZoomAxisFilters, +): ExtremumGetterResult => { + const getter = + axisDirection === 'x' + ? seriesConfig[chartType].xExtremumGetter + : seriesConfig[chartType].yExtremumGetter; + const series = formattedSeries[chartType]?.series ?? {}; + + const [minChartTypeData, maxChartTypeData] = (getter as CartesianExtremumGetter)?.({ + series, + axis, + axisIndex, + isDefaultAxis: axisIndex === 0, + getFilters, + }) ?? [Infinity, -Infinity]; + + const [minData, maxData] = acc; + + return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; +}; + +export const getAxisExtremum = ( + axis: AxisConfig, + axisDirection: 'x' | 'y', + seriesConfig: ChartSeriesConfig, + axisIndex: number, + formattedSeries: ProcessedSeries, + getFilters?: GetZoomAxisFilters, +) => { + const charTypes = Object.keys(seriesConfig) as CartesianChartSeriesType[]; + + const extremums = charTypes.reduce( + (acc, charType) => + axisExtremumCallback( + acc, + charType, + axis, + axisDirection, + seriesConfig, + axisIndex, + formattedSeries, + getFilters, + ), + [Infinity, -Infinity], + ); + + if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { + return [Infinity, -Infinity]; + } + + return extremums; +}; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts new file mode 100644 index 000000000000..5b71d3df5cf9 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts @@ -0,0 +1,6 @@ +export { useChartCartesianAxis } from './useChartCartesianAxis'; +export type { + UseChartCartesianAxisSignature, + UseChartCartesianAxisParameters, + UseChartCartesianAxisDefaultizedParameters, +} from './useChartCartesianAxis.types'; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts new file mode 100644 index 000000000000..30aa73524822 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts @@ -0,0 +1,10 @@ +import { ChartRootSelector, createSelector } from '../../utils/selectors'; +import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; + +export const selectorChartCartesianAxisState: ChartRootSelector = ( + state, +) => state.cartesianAxis; + +export const selectorChartXAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.x); + +export const selectorChartYAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.y); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts new file mode 100644 index 000000000000..a4338cf9f807 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts @@ -0,0 +1,92 @@ +'use client'; +import * as React from 'react'; +import { ChartPlugin } from '../../models'; +import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; +import { blueberryTwilightPalette } from '../../../../colorPalettes'; +import { useSelector } from '../../../store/useSelector'; +import { selectorChartDrawingArea } from '../../corePlugins/useChartDimensions/useChartDimensions.selectors'; +import { computeAxisValue } from './computeAxisValue'; +import { selectorChartSeriesState } from '../../corePlugins/useChartSeries/useChartSeries.selectors'; + +export const useChartCartesianAxis: ChartPlugin = ({ + params, + store, + seriesConfig, +}) => { + const { xAxis, yAxis } = params; + + const drawingArea = useSelector(store, selectorChartDrawingArea); + const formattedSeries = useSelector(store, selectorChartSeriesState); + + React.useEffect(() => { + store.update((prev) => { + return { + ...prev, + cartesianAxis: { + ...prev.cartesianAxis, + x: computeAxisValue({ + drawingArea, + formattedSeries, + axis: xAxis, + seriesConfig, + axisDirection: 'x', + }), + }, + }; + }); + }, [seriesConfig, drawingArea, formattedSeries, xAxis, store]); + + React.useEffect(() => { + store.update((prev) => ({ + ...prev, + cartesianAxis: { + ...prev.cartesianAxis, + y: computeAxisValue({ + drawingArea, + formattedSeries, + axis: yAxis, + seriesConfig, + axisDirection: 'y', + }), + }, + })); + }, [seriesConfig, drawingArea, formattedSeries, yAxis, store]); + + return {}; +}; + +useChartCartesianAxis.params = { + xAxis: true, + yAxis: true, +}; + +useChartCartesianAxis.getDefaultizedParams = ({ params }) => ({ + ...params, + colors: params.colors ?? blueberryTwilightPalette, + theme: params.theme ?? 'light', +}); + +useChartCartesianAxis.getInitialState = ( + { xAxis, yAxis }, + { dimensions, series }, + seriesConfig, +) => { + return { + cartesianAxis: { + x: computeAxisValue({ + drawingArea: dimensions, + formattedSeries: series, + axis: xAxis, + seriesConfig, + axisDirection: 'x', + }), + y: computeAxisValue({ + drawingArea: dimensions, + formattedSeries: series, + axis: yAxis, + seriesConfig, + axisDirection: 'y', + }), + }, + }; +}; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts new file mode 100644 index 000000000000..385bfba07238 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts @@ -0,0 +1,139 @@ +import { ChartPluginSignature } from '../../models'; +import { DatasetType } from '../../../../models/seriesType/config'; +import { + AxisDefaultized, + ScaleName, + ChartsXAxisProps, + ChartsYAxisProps, + AxisId, + AxisConfig, +} from '../../../../models/axis'; +import { UseChartSeriesSignature } from '../../corePlugins/useChartSeries'; + +export type CartesianProviderProps = { + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: AxisConfig[]; + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: AxisConfig[]; + /** + * An array of objects that can be used to populate series and axes data using their `dataKey` property. + */ + dataset?: DatasetType; + children: React.ReactNode; +}; + +export type DefaultizedAxisConfig = { + [axisId: AxisId]: AxisDefaultized; +}; + +export type CartesianContextState = { + /** + * Mapping from x-axis key to scaling configuration. + */ + xAxis: DefaultizedAxisConfig; + /** + * Mapping from y-axis key to scaling configuration. + */ + yAxis: DefaultizedAxisConfig; + /** + * The x-axes IDs sorted by order they got provided. + */ + xAxisIds: AxisId[]; + /** + * The y-axes IDs sorted by order they got provided. + */ + yAxisIds: AxisId[]; +}; + +// export type ZoomData = { axisId: AxisId; start: number; end: number }; + +// export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; +// export type ZoomOptions = Record; + +// export type ZoomAxisFilters = Record; + +// export type GetZoomAxisFilters = (params: { +// currentAxisId: AxisId | undefined; +// seriesXAxisId?: AxisId; +// seriesYAxisId?: AxisId; +// isDefaultAxis: boolean; +// }) => ExtremumFilter; + +export interface UseChartCartesianAxisParameters { + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: AxisConfig[]; + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: AxisConfig[]; +} + +export type UseChartCartesianAxisDefaultizedParameters = UseChartCartesianAxisParameters & {}; + +export interface UseChartCartesianAxisState { + cartesianAxis: { + x: { + /** + * Mapping from x-axis key to scaling configuration. + */ + axis: DefaultizedAxisConfig; + /** + * The x-axes IDs sorted by order they got provided. + */ + axisIds: AxisId[]; + }; + y: { + /** + * Mapping from y-axis key to scaling configuration. + */ + axis: DefaultizedAxisConfig; + /** + * The y-axes IDs sorted by order they got provided. + */ + axisIds: AxisId[]; + }; + }; +} + +export type ExtremumFilter = ( + value: { x: number | Date | string | null; y: number | Date | string | null }, + dataIndex: number, +) => boolean; + +export interface UseChartCartesianAxisInstance {} + +export type UseChartCartesianAxisSignature = ChartPluginSignature<{ + params: UseChartCartesianAxisParameters; + defaultizedParams: UseChartCartesianAxisDefaultizedParameters; + state: UseChartCartesianAxisState; + // instance: UseChartCartesianAxisInstance; + dependencies: [UseChartSeriesSignature]; +}>; + +export type ZoomData = { axisId: AxisId; start: number; end: number }; + +export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; +export type ZoomOptions = Record; + +export type ZoomAxisFilters = Record; + +export type GetZoomAxisFilters = (params: { + currentAxisId: AxisId | undefined; + seriesXAxisId?: AxisId; + seriesYAxisId?: AxisId; + isDefaultAxis: boolean; +}) => ExtremumFilter; diff --git a/packages/x-charts/src/context/CartesianProvider/zoom.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.ts similarity index 100% rename from packages/x-charts/src/context/CartesianProvider/zoom.ts rename to packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.ts diff --git a/packages/x-charts/src/internals/plugins/models/index.ts b/packages/x-charts/src/internals/plugins/models/index.ts index 326d7260e125..0143e86c90f9 100644 --- a/packages/x-charts/src/internals/plugins/models/index.ts +++ b/packages/x-charts/src/internals/plugins/models/index.ts @@ -1,3 +1,4 @@ export * from './helpers'; export * from './plugin'; export * from './chart'; +export * from './seriesConfig'; diff --git a/packages/x-charts/src/internals/plugins/models/plugin.ts b/packages/x-charts/src/internals/plugins/models/plugin.ts index 92c9d64a3db7..f762b8e6f409 100644 --- a/packages/x-charts/src/internals/plugins/models/plugin.ts +++ b/packages/x-charts/src/internals/plugins/models/plugin.ts @@ -1,8 +1,8 @@ import * as React from 'react'; - import type { MergeSignaturesProperty, OptionalIfEmpty } from './helpers'; import type { ChartCorePluginSignatures } from '../corePlugins'; import { ChartStore } from '../utils/ChartStore'; +import { ChartSeriesConfig } from './seriesConfig'; export interface ChartPluginOptions { instance: ChartUsedInstance; @@ -10,6 +10,7 @@ export interface ChartPluginOptions store: ChartUsedStore; svgRef: React.RefObject; plugins: ChartPlugin[]; + seriesConfig: ChartSeriesConfig; } type ChartResponse = OptionalIfEmpty< @@ -82,7 +83,11 @@ export type ChartUsedStore = ChartSt export type ChartPlugin = { (options: ChartPluginOptions): ChartResponse; - getInitialState?: (params: ChartUsedDefaultizedParams) => TSignature['state']; + getInitialState?: ( + params: ChartUsedDefaultizedParams, + currentState: MergeSignaturesProperty, 'state'>, + seriesConfig: ChartSeriesConfig, + ) => TSignature['state']; params: Record; getDefaultizedParams?: (options: { params: ChartUsedParams; diff --git a/packages/x-charts/src/internals/plugins/models/seriesConfig/colorProcessor.types.ts b/packages/x-charts/src/internals/plugins/models/seriesConfig/colorProcessor.types.ts new file mode 100644 index 000000000000..4717add37b06 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/models/seriesConfig/colorProcessor.types.ts @@ -0,0 +1,11 @@ +import type { AxisDefaultized } from '../../../../models/axis'; +import type { DefaultizedSeriesType } from '../../../../models/seriesType'; +import type { ZAxisDefaultized } from '../../../../models/z-axis'; +import type { ChartSeriesType } from '../../../../models/seriesType/config'; + +export type ColorProcessor = ( + series: DefaultizedSeriesType, + xAxis?: AxisDefaultized, + yAxis?: AxisDefaultized, + zAxis?: ZAxisDefaultized, +) => (dataIndex: number) => string; diff --git a/packages/x-charts/src/internals/plugins/models/seriesConfig/extremumGetter.types.ts b/packages/x-charts/src/internals/plugins/models/seriesConfig/extremumGetter.types.ts new file mode 100644 index 000000000000..3d9261096d5c --- /dev/null +++ b/packages/x-charts/src/internals/plugins/models/seriesConfig/extremumGetter.types.ts @@ -0,0 +1,30 @@ +import type { + CartesianChartSeriesType, + ChartSeriesDefaultized, +} from '../../../../models/seriesType/config'; +import type { AxisConfig, AxisId } from '../../../../models/axis'; +import type { SeriesId } from '../../../../models/seriesType/common'; + +type CartesianExtremumGetterParams = { + series: Record>; + axis: AxisConfig; + axisIndex: number; + isDefaultAxis: boolean; + getFilters?: (params: { + currentAxisId: AxisId | undefined; + seriesXAxisId?: AxisId; + seriesYAxisId?: AxisId; + isDefaultAxis: boolean; + }) => CartesianExtremumFilter; +}; + +export type CartesianExtremumGetterResult = [number, number]; + +export type CartesianExtremumGetter = ( + params: CartesianExtremumGetterParams, +) => CartesianExtremumGetterResult; + +export type CartesianExtremumFilter = ( + value: { x: number | Date | string | null; y: number | Date | string | null }, + dataIndex: number, +) => boolean; diff --git a/packages/x-charts/src/internals/plugins/models/seriesConfig/index.ts b/packages/x-charts/src/internals/plugins/models/seriesConfig/index.ts new file mode 100644 index 000000000000..d574a674c8a7 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/models/seriesConfig/index.ts @@ -0,0 +1,4 @@ +export * from './colorProcessor.types'; +export * from './extremumGetter.types'; +export * from './seriesConfig.types'; +export * from './seriesProcessor.types'; diff --git a/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesConfig.types.ts b/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesConfig.types.ts new file mode 100644 index 000000000000..9b4dd0769c4b --- /dev/null +++ b/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesConfig.types.ts @@ -0,0 +1,20 @@ +import { SeriesProcessor } from './seriesProcessor.types'; +import { CartesianChartSeriesType, ChartSeriesType } from '../../../../models/seriesType/config'; +import { ColorProcessor } from './colorProcessor.types'; +import { CartesianExtremumGetter } from './extremumGetter.types'; + +export type ChartSeriesTypeConfig = { + seriesProcessor: SeriesProcessor; + colorProcessor: ColorProcessor; + // rotationExtremumGetters: ExtremumGettersConfig; + // radiusExtremumGetters: ExtremumGettersConfig; +} & (TSeriesType extends CartesianChartSeriesType + ? { + xExtremumGetter: CartesianExtremumGetter; + yExtremumGetter: CartesianExtremumGetter; + } + : {}); + +export type ChartSeriesConfig = { + [Key in TSeriesType]: ChartSeriesTypeConfig; +}; diff --git a/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesProcessor.types.ts b/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesProcessor.types.ts new file mode 100644 index 000000000000..af0d40fc4a96 --- /dev/null +++ b/packages/x-charts/src/internals/plugins/models/seriesConfig/seriesProcessor.types.ts @@ -0,0 +1,32 @@ +import type { + ChartSeriesDefaultized, + ChartSeriesType, + ChartsSeriesConfig, + DatasetType, +} from '../../../../models/seriesType/config'; +import type { SeriesId } from '../../../../models/seriesType/common'; +import { StackingGroupsType } from '../../../stackSeries'; +import type { LegendItemParams } from '../../../../ChartsLegend/chartsLegend.types'; + +export type SeriesProcessorParams = { + series: Record; + seriesOrder: SeriesId[]; +}; + +export type SeriesProcessorResult = { + series: Record>; + seriesOrder: SeriesId[]; +} & (ChartsSeriesConfig[TSeriesType] extends { + canBeStacked: true; +} + ? { stackingGroups: StackingGroupsType } + : {}); + +export type SeriesProcessor = ( + params: SeriesProcessorParams, + dataset?: DatasetType, +) => SeriesProcessorResult; + +export type LegendGetter = ( + series: SeriesProcessorResult, +) => LegendItemParams[]; diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index 80f12a62facf..981f61ff7ce4 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -12,6 +12,8 @@ import { CHART_CORE_PLUGINS, ChartCorePluginSignatures } from '../plugins/corePl import { UseChartBaseProps } from './useCharts.types'; import { UseChartInteractionState } from '../plugins/featurePlugins/useChartInteraction/useChartInteraction.types'; import { extractPluginParamsFromProps } from './extractPluginParamsFromProps'; +import { ChartSeriesType } from '../../models/seriesType/config'; +import { ChartSeriesConfig } from '../plugins/models/seriesConfig'; export function useChartApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -34,7 +36,12 @@ let globalId = 0; export function useCharts< TSignatures extends readonly ChartAnyPluginSignature[], TProps extends Partial>, ->(inPlugins: ConvertSignaturesIntoPlugins, props: TProps) { + TSeriesType extends ChartSeriesType, +>( + inPlugins: ConvertSignaturesIntoPlugins, + props: TProps, + seriesConfig: ChartSeriesConfig, +) { type TSignaturesWithCorePluginSignatures = readonly [ ...ChartCorePluginSignatures, ...TSignatures, @@ -75,7 +82,10 @@ export function useCharts< plugins.forEach((plugin) => { if (plugin.getInitialState) { - Object.assign(initialState, plugin.getInitialState(pluginParams)); + Object.assign( + initialState, + plugin.getInitialState(pluginParams, initialState, seriesConfig), + ); } }); storeRef.current = new ChartStore(initialState); @@ -88,6 +98,7 @@ export function useCharts< plugins: plugins as ChartPlugin[], store: storeRef.current as ChartStore, svgRef: innerSvgRef, + seriesConfig, }); if (pluginResponse.publicAPI) { diff --git a/packages/x-charts/src/internals/store/useStore.ts b/packages/x-charts/src/internals/store/useStore.ts index ba2e8422e455..eb9f0cc3fd22 100644 --- a/packages/x-charts/src/internals/store/useStore.ts +++ b/packages/x-charts/src/internals/store/useStore.ts @@ -1,9 +1,12 @@ import { useChartContext } from '../../context/ChartProvider'; import { ChartStore } from '../plugins/utils/ChartStore'; import { UseChartInteractionSignature } from '../plugins/featurePlugins/useChartInteraction/useChartInteraction.types'; +import { ChartAnyPluginSignature } from '../plugins/models'; // This hook should be removed because user and us should not interact with the store directly, but with public/private APIs -export function useStore(skipError?: boolean): ChartStore<[UseChartInteractionSignature]> { +export function useStore( + skipError?: boolean, +): ChartStore<[...TSignatures, UseChartInteractionSignature]> { const context = useChartContext(); if (skipError) { From b6e2206419eea436236531479fa5f08559abe174 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 10 Dec 2024 17:29:39 +0100 Subject: [PATCH 09/32] WIP --- .../CartesianProviderPro.tsx | 111 ------------- .../src/context/CartesianProviderPro/index.ts | 1 - .../ChartDataProviderPro.tsx | 36 +--- .../createAxisFilterMapper.ts | 13 +- .../defaultizeAxis.ts} | 21 +-- .../defaultizeZoom.ts | 37 +++++ .../getAxisExtremum.ts | 70 ++++++++ .../plugins/useChartProCartesianAxis/index.ts | 6 + .../useChartProCartesianAxis.selectors.ts | 10 ++ .../useChartProCartesianAxis.ts | 121 ++++++++++++++ .../useChartProCartesianAxis.types.ts | 154 ++++++++++++++++++ .../useChartProCartesianAxis.utils.ts | 10 ++ .../plugins/useChartProCartesianAxis/zoom.ts | 23 +++ .../src/ChartContainer/ChartContainer.tsx | 8 +- .../ChartContainer/useChartContainerProps.ts | 9 +- .../src/ChartsTooltip/useAxisTooltip.tsx | 1 + packages/x-charts/src/LineChart/LineChart.tsx | 12 +- .../ChartDataProvider/ChartDataProvider.tsx | 36 ++-- .../useChartDataProviderProps.ts | 33 ++-- .../ChartProvider/ChartProvider.types.ts | 2 +- .../useHighlighted.test.tsx | 15 +- packages/x-charts/src/hooks/useSeries.ts | 4 +- packages/x-charts/src/internals/index.ts | 11 ++ .../corePlugins/useChartDimensions/index.ts | 1 + .../plugins/corePlugins/useChartId/index.ts | 1 + .../corePlugins/useChartId/useChartId.ts | 7 +- .../corePlugins/useChartSeries/index.ts | 1 + .../useChartSeries.selectors.ts | 12 +- .../useChartSeries/useChartSeries.ts | 37 +++-- .../useChartSeries/useChartSeries.types.ts | 19 ++- .../useChartCartesianAxis/computeAxisValue.ts | 34 ++-- .../useChartCartesianAxis/defaultizeAxis.ts | 22 ++- .../useChartCartesianAxis/getAxisExtremum.ts | 26 +-- .../useChartCartesianAxis/index.ts | 1 + .../useChartCartesianAxis.selectors.ts | 57 ++++++- .../useChartCartesianAxis.ts | 79 +++------ .../useChartCartesianAxis.types.ts | 65 ++------ .../src/internals/plugins/models/plugin.ts | 33 ++++ .../src/internals/store/useChartModels.ts | 109 +++++++++++++ .../x-charts/src/internals/store/useCharts.ts | 7 + 40 files changed, 858 insertions(+), 397 deletions(-) delete mode 100644 packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx delete mode 100644 packages/x-charts-pro/src/context/CartesianProviderPro/index.ts rename packages/x-charts-pro/src/{context/CartesianProviderPro => internals/plugins/useChartProCartesianAxis}/createAxisFilterMapper.ts (92%) rename packages/{x-charts/src/context/ChartDataProvider/useDefaultizeAxis.ts => x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts} (55%) create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts create mode 100644 packages/x-charts/src/internals/store/useChartModels.ts diff --git a/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx b/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx deleted file mode 100644 index 555acf19086e..000000000000 --- a/packages/x-charts-pro/src/context/CartesianProviderPro/CartesianProviderPro.tsx +++ /dev/null @@ -1,111 +0,0 @@ -'use client'; -import * as React from 'react'; -import { - useDrawingArea, - useSeries, - CartesianContext, - CartesianProviderProps, - computeAxisValue, - useXExtremumGetter, - useYExtremumGetter, - ZoomAxisFilters, -} from '@mui/x-charts/internals'; -import { useZoom } from '../ZoomProvider/useZoom'; -import { createAxisFilterMapper, createGetAxisFilters } from './createAxisFilterMapper'; - -export interface CartesianProviderProProps extends CartesianProviderProps {} - -function CartesianProviderPro(props: CartesianProviderProProps) { - const { xAxis, yAxis, children } = props; - - const formattedSeries = useSeries(); - const drawingArea = useDrawingArea(); - const { zoomData, options } = useZoom(); - const xExtremumGetters = useXExtremumGetter(); - const yExtremumGetters = useYExtremumGetter(); - - const getFilters = React.useMemo(() => { - const xMapper = createAxisFilterMapper({ - zoomData, - extremumGetter: xExtremumGetters, - formattedSeries, - direction: 'x', - }); - - const yMapper = createAxisFilterMapper({ - zoomData, - extremumGetter: yExtremumGetters, - formattedSeries, - direction: 'y', - }); - - const xFilters = xAxis.reduce((acc, axis, index) => { - const filter = xMapper(axis, index); - if (filter !== null) { - acc[axis.id] = filter; - } - return acc; - }, {} as ZoomAxisFilters); - - const yFilters = yAxis.reduce((acc, axis, index) => { - const filter = yMapper(axis, index); - if (filter !== null) { - acc[axis.id] = filter; - } - return acc; - }, {} as ZoomAxisFilters); - - if (Object.keys(xFilters).length === 0 && Object.keys(yFilters).length === 0) { - return undefined; - } - - return createGetAxisFilters({ ...xFilters, ...yFilters }); - }, [formattedSeries, xAxis, xExtremumGetters, yAxis, yExtremumGetters, zoomData]); - - const xValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: xAxis, - extremumGetters: xExtremumGetters, - axisDirection: 'x', - zoomData, - zoomOptions: options, - getFilters, - }), - [drawingArea, formattedSeries, xAxis, xExtremumGetters, zoomData, options, getFilters], - ); - - const yValues = React.useMemo( - () => - computeAxisValue({ - drawingArea, - formattedSeries, - axis: yAxis, - extremumGetters: yExtremumGetters, - axisDirection: 'y', - zoomData, - zoomOptions: options, - getFilters, - }), - [drawingArea, formattedSeries, yAxis, yExtremumGetters, zoomData, options, getFilters], - ); - - const value = React.useMemo( - () => ({ - isInitialized: true, - data: { - xAxis: xValues.axis, - yAxis: yValues.axis, - xAxisIds: xValues.axisIds, - yAxisIds: yValues.axisIds, - }, - }), - [xValues, yValues], - ); - - return {children}; -} - -export { CartesianProviderPro }; diff --git a/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts b/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts deleted file mode 100644 index 6b24b2347017..000000000000 --- a/packages/x-charts-pro/src/context/CartesianProviderPro/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './CartesianProviderPro'; diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx index 388653077b35..9998c56009bb 100644 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx +++ b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx @@ -1,31 +1,21 @@ 'use client'; import * as React from 'react'; -import { - ChartDataProviderProps, - PluginProvider, - SeriesProvider, - AnimationProvider, - ChartProvider, -} from '@mui/x-charts/internals'; +import { ChartDataProviderProps, AnimationProvider, ChartProvider } from '@mui/x-charts/internals'; import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; import { getReleaseInfo } from '../../internals/utils/releaseInfo'; -import { CartesianProviderPro } from '../CartesianProviderPro'; -import { ZoomProps, ZoomProvider } from '../ZoomProvider'; +import { ZoomProps } from '../ZoomProvider'; import { useChartContainerProProps } from './useChartDataProviderProProps'; +import { useChartProCartesianAxis } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis'; const releaseInfo = getReleaseInfo(); -export interface ChartDataProviderProProps extends ChartDataProviderProps, ZoomProps {} +export interface ChartDataProviderProProps extends ChartDataProviderProps<[UseCa]>, ZoomProps {} function ChartDataProviderPro(props: ChartDataProviderProProps) { const { - zoomProviderProps, - seriesProviderProps, zAxisContextProps, highlightedProviderProps, - cartesianProviderProps, - pluginProviderProps, animationProviderProps, chartProviderProps, children, @@ -34,21 +24,11 @@ function ChartDataProviderPro(props: ChartDataProviderProProps) { useLicenseVerifier('x-charts-pro', releaseInfo); return ( - + - - - - - - - {children} - - - - - - + + {children} + ); diff --git a/packages/x-charts-pro/src/context/CartesianProviderPro/createAxisFilterMapper.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts similarity index 92% rename from packages/x-charts-pro/src/context/CartesianProviderPro/createAxisFilterMapper.ts rename to packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts index 43a65e76688b..3d2518bf6b61 100644 --- a/packages/x-charts-pro/src/context/CartesianProviderPro/createAxisFilterMapper.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts @@ -1,16 +1,7 @@ -import { - getAxisExtremum, - FormattedSeries, - ExtremumGettersConfig, - ExtremumFilter, - ZoomAxisFilters, - GetZoomAxisFilters, - isDefined, - getScale, -} from '@mui/x-charts/internals'; +import { getAxisExtremum, isDefined, getScale } from '@mui/x-charts/internals'; import { ScaleName, AxisConfig } from '@mui/x-charts/models'; import { ChartsAxisProps } from '@mui/x-charts/ChartsAxis'; -import { ZoomData } from '../ZoomProvider'; +import { ZoomData } from '../../../context/ZoomProvider'; type CreateAxisFilterMapperParams = { zoomData: ZoomData[]; diff --git a/packages/x-charts/src/context/ChartDataProvider/useDefaultizeAxis.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts similarity index 55% rename from packages/x-charts/src/context/ChartDataProvider/useDefaultizeAxis.ts rename to packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts index b67d37420799..df07411bade8 100644 --- a/packages/x-charts/src/context/ChartDataProvider/useDefaultizeAxis.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts @@ -1,12 +1,8 @@ -'use client'; -import * as React from 'react'; +import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '@mui/x-charts/constants'; +import { AxisConfig, ChartsAxisProps, DatasetType, ScaleName } from '@mui/x-charts/internals'; import { MakeOptional } from '@mui/x-internals/types'; -import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../../constants'; -import { AxisConfig, ScaleName } from '../../models'; -import { ChartsAxisProps } from '../../models/axis'; -import { DatasetType } from '../../models/seriesType/config'; -const defaultizeAxis = ( +export const defaultizeAxis = ( inAxis: MakeOptional, 'id'>[] | undefined, dataset: DatasetType | undefined, axisName: 'x' | 'y', @@ -33,14 +29,3 @@ const defaultizeAxis = ( }; }); }; - -export const useDefaultizeAxis = ( - inXAxis: MakeOptional, 'id'>[] | undefined, - inYAxis: MakeOptional, 'id'>[] | undefined, - dataset: DatasetType | undefined, -) => { - const xAxis = React.useMemo(() => defaultizeAxis(inXAxis, dataset, 'x'), [inXAxis, dataset]); - const yAxis = React.useMemo(() => defaultizeAxis(inYAxis, dataset, 'y'), [inYAxis, dataset]); - - return [xAxis, yAxis]; -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts new file mode 100644 index 000000000000..811af3ff2e90 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts @@ -0,0 +1,37 @@ +import { AxisId } from '@mui/x-charts/internals'; +import { DefaultizedZoomOptions, ZoomOptions } from './useChartProCartesianAxis.types'; + +const defaultZoomOptions: Required = { + minStart: 0, + maxEnd: 100, + step: 5, + minSpan: 10, + maxSpan: 100, + panning: true, + filterMode: 'keep', +}; + +export const defaultizeZoom = ( + zoom: boolean | ZoomOptions | undefined, + axisId: AxisId, + axisDirection: 'x' | 'y', +): DefaultizedZoomOptions | undefined => { + if (!zoom) { + return undefined; + } + + if (zoom === true) { + return { + axisId, + axisDirection, + ...defaultZoomOptions, + }; + } + + return { + axisId, + axisDirection, + ...defaultZoomOptions, + ...zoom, + }; +}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts new file mode 100644 index 000000000000..da0626d72178 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts @@ -0,0 +1,70 @@ +import { AxisConfig } from '../../../../models'; +import { CartesianChartSeriesType } from '../../../../models/seriesType/config'; +import { ChartSeriesConfig } from '../../models/seriesConfig'; +import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; +import { + CartesianExtremumGetter, + CartesianExtremumGetterResult, +} from '../../models/seriesConfig/extremumGetter.types'; +import { GetZoomAxisFilters } from './useChartProCartesianAxis.types'; + +const axisExtremumCallback = ( + acc: CartesianExtremumGetterResult, + chartType: TSeriesType, + axis: AxisConfig, + axisDirection: 'x' | 'y', + seriesConfig: ChartSeriesConfig, + axisIndex: number, + formattedSeries: ProcessedSeries, + getFilters?: GetZoomAxisFilters, +): CartesianExtremumGetterResult => { + const getter = + axisDirection === 'x' + ? seriesConfig[chartType].xExtremumGetter + : seriesConfig[chartType].yExtremumGetter; + const series = formattedSeries[chartType]?.series ?? {}; + + const [minChartTypeData, maxChartTypeData] = (getter as CartesianExtremumGetter)?.({ + series, + axis, + axisIndex, + isDefaultAxis: axisIndex === 0, + getFilters, + }) ?? [Infinity, -Infinity]; + + const [minData, maxData] = acc; + + return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; +}; + +export const getAxisExtremum = ( + axis: AxisConfig, + axisDirection: 'x' | 'y', + seriesConfig: ChartSeriesConfig, + axisIndex: number, + formattedSeries: ProcessedSeries, + getFilters?: GetZoomAxisFilters, +) => { + const charTypes = Object.keys(seriesConfig) as CartesianChartSeriesType[]; + + const extremums = charTypes.reduce( + (acc, charType) => + axisExtremumCallback( + acc, + charType, + axis, + axisDirection, + seriesConfig, + axisIndex, + formattedSeries, + getFilters, + ), + [Infinity, -Infinity], + ); + + if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { + return [Infinity, -Infinity]; + } + + return extremums; +}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts new file mode 100644 index 000000000000..98382f151e6a --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts @@ -0,0 +1,6 @@ +export { useChartCartesianAxis } from './useChartProCartesianAxis'; +export type { + UseChartCartesianAxisSignature, + UseChartCartesianAxisParameters, + UseChartCartesianAxisDefaultizedParameters, +} from './useChartProCartesianAxis.types'; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts new file mode 100644 index 000000000000..3248e643f4fb --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts @@ -0,0 +1,10 @@ +import { ChartRootSelector, createSelector } from '../../utils/selectors'; +import { UseChartCartesianAxisSignature } from './useChartProCartesianAxis.types'; + +export const selectorChartCartesianAxisState: ChartRootSelector = ( + state, +) => state.cartesianAxis; + +export const selectorChartXAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.x); + +export const selectorChartYAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.y); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts new file mode 100644 index 000000000000..fcccf5f9ca40 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts @@ -0,0 +1,121 @@ +'use client'; +import * as React from 'react'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; +import { + computeAxisValue, + selectorChartDrawingArea, + selectorChartSeriesState, + ChartPlugin, + useSelector, + defaultizeAxis, + AxisId, +} from '@mui/x-charts/internals'; +import { blueberryTwilightPalette } from '@mui/x-charts/colorPalettes'; +import { + DefaultizedZoomOptions, + UseChartProCartesianAxisSignature, + ZoomData, +} from './useChartProCartesianAxis.types'; +import { defaultizeZoom } from './defaultizeZoom'; +import { createZoomMap } from './useChartProCartesianAxis.utils'; + +export const useChartProCartesianAxis: ChartPlugin = ({ + params, + store, + models, +}) => { + useEnhancedEffect(() => { + store.update((prevState) => ({ + ...prevState, + zoom: { + ...prevState.zoom, + zoomMap: createZoomMap(models.zoom.value), + }, + })); + }, [store, models.zoom.value]); + + const { xAxis, yAxis, dataset } = params; + + + // The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartProCartesianAxis` + // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one + const isFirstRender = React.useRef(true); + React.useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + const defaultizedXAxis = defaultizeAxis(xAxis, dataset, 'x'); + const defaultizedYAxis = defaultizeAxis(yAxis, dataset, 'y'); + store.update((prev) => { + return { + ...prev, + cartesianAxis: { + x: defaultizedXAxis, + y: defaultizedYAxis, + }, + }; + }); + }, [xAxis, yAxis, dataset, store]); + + return {}; +}; + +useChartProCartesianAxis.params = { + xAxis: true, + yAxis: true, + dataset: true, + zoom: true, + onZoomChange: true, +}; + +useChartProCartesianAxis.getDefaultizedParams = ({ params }) => ({ + ...params, + colors: params.colors ?? blueberryTwilightPalette, + theme: params.theme ?? 'light', +}); + +const DEFAULT_ZOOMS: ZoomData[] = []; + +useChartProCartesianAxis.models = { + zoom: { + getDefaultValue: () => DEFAULT_ZOOMS, + }, +}; + +useChartProCartesianAxis.getInitialState = (params) => { + const defaultizedXAxis = defaultizeAxis(params.xAxis, params.dataset, 'x'); + const defaultizedYAxis = defaultizeAxis(params.yAxis, params.dataset, 'y'); + + const options = { + ...defaultizedXAxis.reduce>((acc, v) => { + const { zoom, id: axisId } = v; + const defaultizedZoom = defaultizeZoom(zoom, axisId, 'x'); + if (defaultizedZoom) { + acc[axisId] = defaultizedZoom; + } + return acc; + }, {}), + ...defaultizedYAxis.reduce>((acc, v) => { + const { zoom, id: axisId } = v; + const defaultizedZoom = defaultizeZoom(zoom, axisId, 'y'); + if (defaultizedZoom) { + acc[axisId] = defaultizedZoom; + } + return acc; + }, {}), + }; + + return { + zoom: { + options, + zoomMap: createZoomMap(params.zoom === undefined ? [] : params.zoom), + isInteracting: false, + }, + cartesianAxis: { + x: defaultizedXAxis, + y: defaultizedYAxis, + }, + }; +}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts new file mode 100644 index 000000000000..8b11b42796d8 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts @@ -0,0 +1,154 @@ +import { MakeOptional } from '@mui/x-internals/types'; +import { + AxisDefaultized, + ScaleName, + ChartsXAxisProps, + ChartsYAxisProps, + AxisId, + AxisConfig, + UseChartSeriesSignature, + DatasetType, + ChartPluginSignature, +} from '@mui/x-charts/internals'; + +export type DefaultizedAxisConfig = { + [axisId: AxisId]: AxisDefaultized; +}; + +export interface UseChartProCartesianAxisParameters { + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis?: MakeOptional, 'id'>[]; + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis?: MakeOptional, 'id'>[]; + dataset?: DatasetType; + /** + * The list of zoom data related to each axis. + */ + zoom?: ZoomData[]; + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange?: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void; +} + +export type UseChartProCartesianAxisDefaultizedParameters = UseChartProCartesianAxisParameters & {}; + +export type ZoomOptions = { + /** + * The starting percentage of the zoom range. In the range of 0 to 100. + * + * @default 0 + */ + minStart?: number; + /** + * The ending percentage of the zoom range. In the range of 0 to 100. + * + * @default 100 + */ + maxEnd?: number; + /** + * The step size of the zooming function. Defines the granularity of the zoom. + * + * @default 5 + */ + step?: number; + /** + * Restricts the minimum span size in the range of 0 to 100. + * + * If the span size is smaller than the minSpan, the span will be resized to the minSpan. + * + * @default 10 + */ + minSpan?: number; + /** + * Restricts the maximum span size in the range of 0 to 100. + * + * If the span size is larger than the maxSpan, the span will be resized to the maxSpan. + * + * @default 100 + */ + maxSpan?: number; + /** + * Set to `false` to disable panning. Useful when you want to pan programmatically, + * or to show only a specific section of the chart. + * + * @default true + */ + panning?: boolean; + /** + * Defines how to filter the axis data when it is outside of the zoomed range of this axis. + * + * - `keep`: The data outside the zoomed range is kept. And the other axes will stay the same. + * - `discard`: The data outside the zoomed range is discarded for the other axes. + * The other axes will be adjusted to fit the zoomed range. + * + * @default 'keep' + */ + filterMode?: 'discard' | 'keep'; +}; + +export type DefaultizedZoomOptions = Required & { + axisId: AxisId; + axisDirection: 'x' | 'y'; +}; + +export interface UseChartProCartesianAxisState { + zoom: { + /** + * The zoom options for each axis. + */ + options: Record; + /** + * Whether the user is currently interacting with the chart. + * This is useful to prevent animations from running while the user is interacting. + */ + isInteracting: boolean; + /** + * Mapping of axis id to the zoom data. + */ + zoomMap: Map; + }; + cartesianAxis: { + x: DefaultizedAxisConfig; + y: DefaultizedAxisConfig; + }; +} + +export type ExtremumFilter = ( + value: { x: number | Date | string | null; y: number | Date | string | null }, + dataIndex: number, +) => boolean; + +export interface UseChartProCartesianAxisInstance {} + +export type UseChartProCartesianAxisSignature = ChartPluginSignature<{ + params: UseChartProCartesianAxisParameters; + defaultizedParams: UseChartProCartesianAxisDefaultizedParameters; + state: UseChartProCartesianAxisState; + // instance: UseChartProCartesianAxisInstance; + modelNames: 'zoom'; + dependencies: [UseChartSeriesSignature]; +}>; + +export type ZoomData = { axisId: AxisId; start: number; end: number }; + +export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; + +export type ZoomAxisFilters = Record; + +export type GetZoomAxisFilters = (params: { + currentAxisId: AxisId | undefined; + seriesXAxisId?: AxisId; + seriesYAxisId?: AxisId; + isDefaultAxis: boolean; +}) => ExtremumFilter; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts new file mode 100644 index 000000000000..304813ccff66 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts @@ -0,0 +1,10 @@ +import { AxisId } from '@mui/x-charts/internals'; +import { ZoomData } from './useChartProCartesianAxis.types'; + +export const createZoomMap = (zoom: ZoomData[]) => { + const selectedItemsMap = new Map(); + zoom.forEach((zoomItem) => { + selectedItemsMap.set(zoomItem.axisId, zoomItem); + }); + return selectedItemsMap; +}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts new file mode 100644 index 000000000000..57ce8e20a4c8 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts @@ -0,0 +1,23 @@ +/** + * Applies the zoom into the scale range. + * It changes the screen coordinates that the scale covers. + * Not the data that is displayed. + * + * @param scaleRange the original range in real screen coordinates. + * @param zoomRange the zoom range in percentage. + * @returns zoomed range in real screen coordinates. + */ +export const zoomScaleRange = ( + scaleRange: [number, number] | number[], + zoomRange: [number, number] | number[], +) => { + const rangeGap = scaleRange[1] - scaleRange[0]; + const zoomGap = zoomRange[1] - zoomRange[0]; + + // If current zoom show the scale between p1 and p2 percents + // The range should be extended by adding [0, p1] and [p2, 100] segments + const min = scaleRange[0] - (zoomRange[0] * rangeGap) / zoomGap; + const max = scaleRange[1] + ((100 - zoomRange[1]) * rangeGap) / zoomGap; + + return [min, max]; +}; diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index a938fb051e30..62b3cbea36c9 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -1,11 +1,15 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; +import { ChartSeriesType } from '../models/seriesType/config'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; import { useChartContainerProps } from './useChartContainerProps'; import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; +import { UseChartCartesianAxisSignature } from '../internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types'; -export interface ChartContainerProps extends ChartDataProviderProps, ChartsSurfaceProps {} +export interface ChartContainerProps + extends ChartDataProviderProps<[UseChartCartesianAxisSignature]>, + ChartsSurfaceProps {} /** * It sets up the data providers as well as the `` for the chart. @@ -41,7 +45,7 @@ const ChartContainer = React.forwardRef(function ChartContainer( ); return ( - + {...chartDataProviderProps}> {children} ); diff --git a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts index 12e1a9edc178..4355193caf50 100644 --- a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts +++ b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts @@ -3,9 +3,13 @@ import * as React from 'react'; import { ChartsSurfaceProps } from '../ChartsSurface'; import { ChartDataProviderProps } from '../context/ChartDataProvider'; import type { ChartContainerProps } from './ChartContainer'; +import { + useChartCartesianAxis, + UseChartCartesianAxisSignature, +} from '../internals/plugins/featurePlugins/useChartCartesianAxis'; export type UseChartContainerPropsReturnValue = { - chartDataProviderProps: ChartDataProviderProps; + chartDataProviderProps: ChartDataProviderProps<[UseChartCartesianAxisSignature]>; chartsSurfaceProps: ChartsSurfaceProps & { ref: React.Ref }; children: React.ReactNode; }; @@ -44,7 +48,7 @@ export const useChartContainerProps = ( ...other, }; - const chartDataProviderProps: ChartDataProviderProps = { + const chartDataProviderProps: ChartDataProviderProps<[UseChartCartesianAxisSignature]> = { margin, series, colors, @@ -57,6 +61,7 @@ export const useChartContainerProps = ( skipAnimation, width, height, + plugins: [useChartCartesianAxis], }; return { diff --git a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx index c62965daaddc..5ce01f222094 100644 --- a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx @@ -49,6 +49,7 @@ export function useAxisTooltip(): null | UseAxisTooltipReturnValue { const series = useSeries(); + const { xAxis } = useXAxes(); const { yAxis } = useYAxes(); diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 6b36690dca8c..6cd7ead06de8 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -54,14 +54,14 @@ export interface LineChartSlotProps export interface LineChartProps extends Omit, - Omit, + // Omit, Omit, ChartsOnAxisClickHandlerProps { - /** - * The series to display in the line chart. - * An array of [[LineSeriesType]] objects. - */ - series: MakeOptional[]; + // /** + // * The series to display in the line chart. + // * An array of [[LineSeriesType]] objects. + // */ + // series: MakeOptional[]; /** * Option to display a cartesian grid in the background. */ diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index bc600c86f01b..f3fa5c2dadfc 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -1,34 +1,29 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { MakeOptional } from '@mui/x-internals/types'; import { useChartDataProviderProps } from './useChartDataProviderProps'; -import { AxisConfig, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from '../../models/axis'; import { AnimationProvider, AnimationProviderProps } from '../AnimationProvider'; import { ZAxisContextProvider, ZAxisContextProviderProps } from '../ZAxisContextProvider'; import { HighlightedProvider, HighlightedProviderProps } from '../HighlightedProvider'; import { ChartProvider, ChartProviderProps } from '../ChartProvider'; -import { useChartCartesianAxis } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; +// import { +// useChartCartesianAxis, +// UseChartCartesianAxisSignature, +// } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; +import { ChartSeriesType } from '../../models/seriesType/config'; +import { ChartAnyPluginSignature } from '../../internals/plugins/models/plugin'; -export type ChartDataProviderProps = Omit< +export type ChartDataProviderProps< + TSignatures extends readonly ChartAnyPluginSignature[], + TSeries extends ChartSeriesType = ChartSeriesType, +> = Omit< ZAxisContextProviderProps & HighlightedProviderProps & AnimationProviderProps & - ChartProviderProps<[]>['pluginParams'], + ChartProviderProps['pluginParams'], 'children' > & { - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis?: MakeOptional, 'id'>[]; - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis?: MakeOptional, 'id'>[]; + plugins?: ChartProviderProps['plugins']; children?: React.ReactNode; }; @@ -59,7 +54,10 @@ export type ChartDataProviderProps = Omit< * * ``` */ -function ChartDataProvider(props: ChartDataProviderProps) { +function ChartDataProvider< + TSignatures extends readonly ChartAnyPluginSignature[], + TSeries extends ChartSeriesType = ChartSeriesType, +>(props: ChartDataProviderProps) { const { children, zAxisContextProps, @@ -69,7 +67,7 @@ function ChartDataProvider(props: ChartDataProviderProps) { } = useChartDataProviderProps(props); return ( - + {...chartProviderProps}> {children} diff --git a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts index 37a1308c3be5..3efae0a20598 100644 --- a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts +++ b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts @@ -3,19 +3,23 @@ import { useTheme } from '@mui/material/styles'; import type { ZAxisContextProviderProps } from '../ZAxisContextProvider'; import type { ChartDataProviderProps } from './ChartDataProvider'; import { HighlightedProviderProps } from '../HighlightedProvider'; -import { useDefaultizeAxis } from './useDefaultizeAxis'; import { AnimationProviderProps } from '../AnimationProvider'; import { ChartProviderProps } from '../ChartProvider'; -import { UseChartCartesianAxisSignature } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; +import { ChartAnyPluginSignature, MergeSignaturesProperty } from '../../internals/plugins/models'; +import { ChartSeriesType } from '../../models/seriesType/config'; +import { ChartCorePluginSignatures } from '../../internals/plugins/corePlugins'; -export const useChartDataProviderProps = (props: ChartDataProviderProps) => { +export const useChartDataProviderProps = < + TSignatures extends readonly ChartAnyPluginSignature[], + TSeries extends ChartSeriesType = ChartSeriesType, +>( + props: ChartDataProviderProps, +) => { const { width, height, series, margin, - xAxis, - yAxis, zAxis, colors, dataset, @@ -23,15 +27,14 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { onHighlightChange, children, skipAnimation, + plugins, + ...other } = props; const theme = useTheme(); - const [defaultizedXAxis, defaultizedYAxis] = useDefaultizeAxis(xAxis, yAxis, dataset); - const chartProviderProps: Omit< - ChartProviderProps<[UseChartCartesianAxisSignature]>, - 'children' - > = { + const chartProviderProps: Omit, 'children'> = { + plugins, pluginParams: { width, height, @@ -40,9 +43,11 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { series, colors, theme: theme.palette.mode, - xAxis: defaultizedXAxis, - yAxis: defaultizedYAxis, - }, + ...other, + } as unknown as MergeSignaturesProperty< + [...ChartCorePluginSignatures, ...TSignatures], + 'params' + >, }; const animationProviderProps: Omit = { @@ -64,8 +69,6 @@ export const useChartDataProviderProps = (props: ChartDataProviderProps) => { zAxisContextProps, highlightedProviderProps, animationProviderProps, - xAxis: defaultizedXAxis, - yAxis: defaultizedYAxis, chartProviderProps, }; }; diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index eb723938d818..70254d8adc23 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -34,7 +34,7 @@ export type ChartContextValue< }; export interface ChartProviderProps< - TSignatures extends readonly ChartAnyPluginSignature[] = [], + TSignatures extends readonly ChartAnyPluginSignature[], TSeries extends ChartSeriesType = ChartSeriesType, > { plugins?: ConvertSignaturesIntoPlugins; diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx index fb17106413fd..631c6a74aa29 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx @@ -3,8 +3,7 @@ import { expect } from 'chai'; import { ErrorBoundary, createRenderer, screen, reactMajor } from '@mui/internal-test-utils'; import { useHighlighted } from './useHighlighted'; import { HighlightedProvider } from './HighlightedProvider'; -import { SeriesProvider } from '../SeriesProvider'; -import { PluginProvider } from '../PluginProvider'; +import { ChartProvider } from '../ChartProvider'; function UseHighlighted() { const { highlightedItem } = useHighlighted(); @@ -48,13 +47,11 @@ describe('useHighlighted', () => { it('should not throw an error when parent context is present', () => { render( - - - - - - - , + + + + + , ); expect(screen.getByText('test-id')).toBeVisible(); diff --git a/packages/x-charts/src/hooks/useSeries.ts b/packages/x-charts/src/hooks/useSeries.ts index 38fb374e64c9..ed1e54bf26fe 100644 --- a/packages/x-charts/src/hooks/useSeries.ts +++ b/packages/x-charts/src/hooks/useSeries.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { useStore } from '../internals/store/useStore'; import { useSelector } from '../internals/store/useSelector'; -import { selectorChartSeriesState } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors'; +import { selectorChartSeriesProcessed } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors'; import { UseChartSeriesSignature } from '../internals/plugins/corePlugins/useChartSeries'; /** @@ -13,7 +13,7 @@ import { UseChartSeriesSignature } from '../internals/plugins/corePlugins/useCha */ export function useSeries() { const store = useStore<[UseChartSeriesSignature]>(); - return useSelector(store, selectorChartSeriesState); + return useSelector(store, selectorChartSeriesProcessed); } /** diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index fda48ee8a263..6efb810464a3 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -11,6 +11,17 @@ export { useBarChartProps } from '../BarChart/useBarChartProps'; export * from '../ChartContainer/useChartContainerProps'; export * from '../context/ChartDataProvider/useChartDataProviderProps'; +// plugins +export * from './plugins/corePlugins/useChartId'; +export * from './plugins/corePlugins/useChartSeries'; +export * from './plugins/corePlugins/useChartDimensions'; +export * from './plugins/featurePlugins/useChartCartesianAxis'; +export * from './plugins/featurePlugins/useChartInteraction'; + +export * from './store/useCharts'; +export * from './store/useStore'; +export * from './store/useSelector'; + // utils export * from './defaultizeValueFormatter'; export * from './configInit'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts index c3fc308d2d8e..71648d1a0fee 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartDimensions/index.ts @@ -4,3 +4,4 @@ export type { UseChartDimensionsParameters, UseChartDimensionsDefaultizedParameters, } from './useChartDimensions.types'; +export * from './useChartDimensions.selectors'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/index.ts index 40532968814f..f78280d4209d 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/index.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/index.ts @@ -4,3 +4,4 @@ export type { UseChartIdParameters, UseChartIdDefaultizedParameters, } from './useChartId.types'; +export * from './useChartId.selectors'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts index e84d650eea36..8b4a6858759b 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.ts @@ -6,7 +6,10 @@ import { createChartDefaultId } from './useChartId.utils'; export const useChartId: ChartPlugin = ({ params, store }) => { React.useEffect(() => { store.update((prevState) => { - if (params.id === prevState.id.providedChartId && prevState.id.chartId !== undefined) { + if ( + params.id === undefined || + (params.id === prevState.id.providedChartId && prevState.id.chartId !== undefined) + ) { return prevState; } @@ -24,5 +27,5 @@ useChartId.params = { }; useChartId.getInitialState = ({ id }) => ({ - id: { chartId: undefined, providedChartId: id }, + id: { chartId: id, providedChartId: id }, }); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts index c2a75681bb0d..3c31d3697da6 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts @@ -4,3 +4,4 @@ export type { UseChartSeriesParameters, UseChartSeriesDefaultizedParameters, } from './useChartSeries.types'; +export * from './useChartSeries.selectors'; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts index 9e8262fd7ed0..44ab139a9575 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.selectors.ts @@ -1,5 +1,15 @@ -import { ChartRootSelector } from '../../utils/selectors'; +import { ChartRootSelector, createSelector } from '../../utils/selectors'; import { UseChartSeriesSignature } from './useChartSeries.types'; export const selectorChartSeriesState: ChartRootSelector = (state) => state.series; + +export const selectorChartSeriesProcessed = createSelector( + selectorChartSeriesState, + (seriesState) => seriesState.processedSeries, +); + +export const selectorChartSeriesConfig = createSelector( + selectorChartSeriesState, + (seriesState) => seriesState.seriesConfig, +); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts index 97394dd86aa5..2722fe2e3a46 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts @@ -12,15 +12,27 @@ export const useChartSeries: ChartPlugin = ({ }) => { const { series = [], dataset, theme, colors } = params; + // The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartSeries` + // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one + const isFirstRender = React.useRef(true); + React.useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + store.update((prev) => ({ ...prev, - series: preprocessSeries({ - series, - colors: typeof colors === 'function' ? colors(theme) : colors, - seriesConfig, - dataset, - }), + series: { + ...prev.series, + preprocessSeries: preprocessSeries({ + series, + colors: typeof colors === 'function' ? colors(theme) : colors, + seriesConfig, + dataset, + }), + }, })); }, [colors, dataset, series, theme, seriesConfig, store]); @@ -42,11 +54,14 @@ useChartSeries.getDefaultizedParams = ({ params }) => ({ useChartSeries.getInitialState = ({ series = [], colors, theme, dataset }, _, seriesConfig) => { return { - series: preprocessSeries({ - series, - colors: typeof colors === 'function' ? colors(theme) : colors, + series: { seriesConfig, - dataset, - }), + processedSeries: preprocessSeries({ + series, + colors: typeof colors === 'function' ? colors(theme) : colors, + seriesConfig, + dataset, + }), + }, }; }; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts index ff9305ed6966..3896fc45ed0a 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts @@ -1,6 +1,6 @@ import { AllSeriesType } from '../../../../models/seriesType'; import { ChartsColorPalette } from '../../../../colorPalettes'; -import { ChartPluginSignature } from '../../models'; +import { ChartPluginSignature, ChartSeriesConfig } from '../../models'; import { ChartSeriesType, DatasetType } from '../../../../models/seriesType/config'; import { SeriesProcessorResult } from '../../models/seriesConfig/seriesProcessor.types'; @@ -40,15 +40,16 @@ export type ProcessedSeries; }; -export interface UseChartSeriesState { - series: ProcessedSeries; +export interface UseChartSeriesState { + series: { processedSeries: ProcessedSeries; seriesConfig: ChartSeriesConfig }; } export interface UseChartSeriesInstance {} -export type UseChartSeriesSignature = ChartPluginSignature<{ - params: UseChartSeriesParameters; - defaultizedParams: UseChartSeriesDefaultizedParameters; - state: UseChartSeriesState; - instance: UseChartSeriesInstance; -}>; +export type UseChartSeriesSignature = + ChartPluginSignature<{ + params: UseChartSeriesParameters; + defaultizedParams: UseChartSeriesDefaultizedParameters; + state: UseChartSeriesState; + instance: UseChartSeriesInstance; + }>; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts index 3e9d5017fa36..28bbc1e7417a 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts @@ -7,7 +7,7 @@ import { isBandScaleConfig, isPointScaleConfig, } from '../../../../models/axis'; -import { ChartSeriesType } from '../../../../models/seriesType/config'; +import { CartesianChartSeriesType, ChartSeriesType } from '../../../../models/seriesType/config'; import { getColorScale, getOrdinalColorScale } from '../../../colorScale'; import { getTickNumber } from '../../../../hooks/useTicks'; import { getScale } from '../../../getScale'; @@ -77,40 +77,28 @@ type ComputeResult = { axisIds: string[]; }; -type ComputeCommonParams = { +type ComputeCommonParams = { drawingArea: ChartDrawingArea; - formattedSeries: ProcessedSeries; - seriesConfig: ChartSeriesConfig; + formattedSeries: ProcessedSeries; + seriesConfig: ChartSeriesConfig; zoomData?: ZoomData[]; zoomOptions?: ZoomOptions; getFilters?: GetZoomAxisFilters; }; -export function computeAxisValue( - options: ComputeCommonParams & { +export function computeAxisValue( + options: ComputeCommonParams & { axis: AxisConfig[]; axisDirection: 'y'; }, ): ComputeResult; -export function computeAxisValue( - options: ComputeCommonParams & { +export function computeAxisValue( + options: ComputeCommonParams & { axis: AxisConfig[]; axisDirection: 'x'; }, ): ComputeResult; -// export function computeAxisValue( -// options: ComputeCommonParams & { -// axis: AxisConfig[]; -// axisDirection: 'radius'; -// }, -// ): ComputeResult; -// export function computeAxisValue( -// options: ComputeCommonParams & { -// axis: AxisConfig[]; -// axisDirection: 'rotation'; -// }, -// ): ComputeResult; -export function computeAxisValue({ +export function computeAxisValue({ drawingArea, formattedSeries, axis: allAxis, @@ -119,7 +107,7 @@ export function computeAxisValue({ zoomData, zoomOptions, getFilters, -}: ComputeCommonParams & { +}: ComputeCommonParams & { axis: AxisConfig[]; axisDirection: 'x' | 'y'; // | 'radius' | 'rotation'; }) { @@ -134,7 +122,7 @@ export function computeAxisValue({ const [minData, maxData] = getAxisExtremum( axis, axisDirection, - seriesConfig, + seriesConfig as ChartSeriesConfig, axisIndex, formattedSeries, zoom === undefined && !zoomOption ? getFilters : undefined, // Do not apply filtering if zoom is already defined. diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts index 6a357388a6cd..e7fb2ea61e78 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts @@ -2,11 +2,13 @@ import { MakeOptional } from '@mui/x-internals/types'; import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../../../../constants'; import { AxisConfig, ScaleName } from '../../../../models'; import { ChartsAxisProps } from '../../../../models/axis'; +import { DatasetType } from '../../../../models/seriesType/config'; -export const defaultizeAxis = ( +export function defaultizeAxis( inAxis: MakeOptional, 'id'>[] | undefined, + dataset: DatasetType | undefined, axisName: 'x' | 'y', -) => { +) { const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY; return [ @@ -15,5 +17,17 @@ export const defaultizeAxis = ( ...(inAxis === undefined || inAxis.findIndex(({ id }) => id === DEFAULT_AXIS_KEY) === -1 ? [{ id: DEFAULT_AXIS_KEY, scaleType: 'linear' as const }] : []), - ]; -}; + ].map((axisConfig) => { + const dataKey = axisConfig.dataKey; + if (dataKey === undefined || axisConfig.data !== undefined) { + return axisConfig; + } + if (dataset === undefined) { + throw new Error(`MUI X: ${axisName}-axis uses \`dataKey\` but no \`dataset\` is provided.`); + } + return { + ...axisConfig, + data: dataset.map((d) => d[dataKey]), + }; + }); +} diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts index bc8536f0e71d..5237c3391b49 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts @@ -2,19 +2,23 @@ import { AxisConfig } from '../../../../models'; import { CartesianChartSeriesType } from '../../../../models/seriesType/config'; import { ChartSeriesConfig } from '../../models/seriesConfig'; import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; -import { CartesianExtremumGetter } from '../../models/seriesConfig/extremumGetter.types'; -import { ExtremumGetterResult, GetZoomAxisFilters } from './useChartCartesianAxis.types'; +import { + CartesianExtremumGetter, + CartesianExtremumGetterResult, +} from '../../models/seriesConfig/extremumGetter.types'; +import { GetZoomAxisFilters } from './useChartCartesianAxis.types'; +import { isCartesianSeriesType } from '../../../isCartesian'; const axisExtremumCallback = ( - acc: ExtremumGetterResult, + acc: CartesianExtremumGetterResult, chartType: TSeriesType, axis: AxisConfig, axisDirection: 'x' | 'y', seriesConfig: ChartSeriesConfig, axisIndex: number, - formattedSeries: ProcessedSeries, + formattedSeries: ProcessedSeries, getFilters?: GetZoomAxisFilters, -): ExtremumGetterResult => { +): CartesianExtremumGetterResult => { const getter = axisDirection === 'x' ? seriesConfig[chartType].xExtremumGetter @@ -34,21 +38,21 @@ const axisExtremumCallback = ( return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; }; -export const getAxisExtremum = ( +export const getAxisExtremum = ( axis: AxisConfig, axisDirection: 'x' | 'y', - seriesConfig: ChartSeriesConfig, + seriesConfig: ChartSeriesConfig, axisIndex: number, - formattedSeries: ProcessedSeries, + formattedSeries: ProcessedSeries, getFilters?: GetZoomAxisFilters, ) => { - const charTypes = Object.keys(seriesConfig) as CartesianChartSeriesType[]; + const charTypes = Object.keys(seriesConfig).filter(isCartesianSeriesType); - const extremums = charTypes.reduce( + const extremums = charTypes.reduce( (acc, charType) => axisExtremumCallback( acc, - charType, + charType as T, axis, axisDirection, seriesConfig, diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts index 5b71d3df5cf9..db358f39ba44 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts @@ -4,3 +4,4 @@ export type { UseChartCartesianAxisParameters, UseChartCartesianAxisDefaultizedParameters, } from './useChartCartesianAxis.types'; +export { defaultizeAxis } from './defaultizeAxis'; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts index 30aa73524822..3c5ead144cef 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts @@ -1,10 +1,57 @@ +import { selectorChartDrawingArea } from '../../corePlugins/useChartDimensions'; +import { + selectorChartSeriesConfig, + selectorChartSeriesProcessed, +} from '../../corePlugins/useChartSeries'; +import { ChartSeriesType } from '../../../../models/seriesType/config'; import { ChartRootSelector, createSelector } from '../../utils/selectors'; +import { computeAxisValue } from './computeAxisValue'; import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; -export const selectorChartCartesianAxisState: ChartRootSelector = ( - state, -) => state.cartesianAxis; +export const selectorChartCartesianAxisState: ChartRootSelector< + UseChartCartesianAxisSignature +> = (state) => state.cartesianAxis; -export const selectorChartXAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.x); +export const selectorChartRawXAxis = createSelector( + selectorChartCartesianAxisState, + (axis) => axis.x, +); -export const selectorChartYAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.y); +export const selectorChartXAxis = createSelector( + [ + selectorChartRawXAxis, + selectorChartDrawingArea, + selectorChartSeriesProcessed, + selectorChartSeriesConfig, + ], + (axis, drawingArea, formattedSeries, seriesConfig) => + computeAxisValue({ + drawingArea, + formattedSeries, + axis, + seriesConfig, + axisDirection: 'x', + }), +); + +export const selectorChartRawYAxis = createSelector( + selectorChartCartesianAxisState, + (axis) => axis.y, +); + +export const selectorChartYAxis = createSelector( + [ + selectorChartRawYAxis, + selectorChartDrawingArea, + selectorChartSeriesProcessed, + selectorChartSeriesConfig, + ], + (axis, drawingArea, formattedSeries, seriesConfig) => + computeAxisValue({ + drawingArea, + formattedSeries, + axis, + seriesConfig, + axisDirection: 'y', + }), +); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts index a4338cf9f807..b0419785101d 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts @@ -5,52 +5,36 @@ import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; import { blueberryTwilightPalette } from '../../../../colorPalettes'; import { useSelector } from '../../../store/useSelector'; import { selectorChartDrawingArea } from '../../corePlugins/useChartDimensions/useChartDimensions.selectors'; -import { computeAxisValue } from './computeAxisValue'; import { selectorChartSeriesState } from '../../corePlugins/useChartSeries/useChartSeries.selectors'; +import { defaultizeAxis } from './defaultizeAxis'; +import { ChartSeriesType } from '../../../../models/seriesType/config'; -export const useChartCartesianAxis: ChartPlugin = ({ - params, - store, - seriesConfig, -}) => { - const { xAxis, yAxis } = params; +export const useChartCartesianAxis: ChartPlugin< + UseChartCartesianAxisSignature +> = ({ params, store, seriesConfig }) => { + const { xAxis, yAxis, dataset } = params; const drawingArea = useSelector(store, selectorChartDrawingArea); const formattedSeries = useSelector(store, selectorChartSeriesState); + // The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartCartesianAxis` + // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one + const isFirstRender = React.useRef(true); React.useEffect(() => { - store.update((prev) => { - return { - ...prev, - cartesianAxis: { - ...prev.cartesianAxis, - x: computeAxisValue({ - drawingArea, - formattedSeries, - axis: xAxis, - seriesConfig, - axisDirection: 'x', - }), - }, - }; - }); - }, [seriesConfig, drawingArea, formattedSeries, xAxis, store]); + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } - React.useEffect(() => { store.update((prev) => ({ ...prev, cartesianAxis: { ...prev.cartesianAxis, - y: computeAxisValue({ - drawingArea, - formattedSeries, - axis: yAxis, - seriesConfig, - axisDirection: 'y', - }), + x: defaultizeAxis(xAxis, dataset, 'x'), + y: defaultizeAxis(yAxis, dataset, 'y'), }, })); - }, [seriesConfig, drawingArea, formattedSeries, yAxis, store]); + }, [seriesConfig, drawingArea, formattedSeries, xAxis, yAxis, dataset, store]); return {}; }; @@ -58,6 +42,7 @@ export const useChartCartesianAxis: ChartPlugin useChartCartesianAxis.params = { xAxis: true, yAxis: true, + dataset: true, }; useChartCartesianAxis.getDefaultizedParams = ({ params }) => ({ @@ -66,27 +51,9 @@ useChartCartesianAxis.getDefaultizedParams = ({ params }) => ({ theme: params.theme ?? 'light', }); -useChartCartesianAxis.getInitialState = ( - { xAxis, yAxis }, - { dimensions, series }, - seriesConfig, -) => { - return { - cartesianAxis: { - x: computeAxisValue({ - drawingArea: dimensions, - formattedSeries: series, - axis: xAxis, - seriesConfig, - axisDirection: 'x', - }), - y: computeAxisValue({ - drawingArea: dimensions, - formattedSeries: series, - axis: yAxis, - seriesConfig, - axisDirection: 'y', - }), - }, - }; -}; +useChartCartesianAxis.getInitialState = ({ xAxis, yAxis, dataset }) => ({ + cartesianAxis: { + x: defaultizeAxis(xAxis, dataset, 'x'), + y: defaultizeAxis(yAxis, dataset, 'y'), + }, +}); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts index 385bfba07238..275c9b3456cd 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts @@ -1,5 +1,6 @@ +import { MakeOptional } from '@mui/x-internals/types'; import { ChartPluginSignature } from '../../models'; -import { DatasetType } from '../../../../models/seriesType/config'; +import { ChartSeriesType, DatasetType } from '../../../../models/seriesType/config'; import { AxisDefaultized, ScaleName, @@ -10,26 +11,6 @@ import { } from '../../../../models/axis'; import { UseChartSeriesSignature } from '../../corePlugins/useChartSeries'; -export type CartesianProviderProps = { - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: AxisConfig[]; - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: AxisConfig[]; - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset?: DatasetType; - children: React.ReactNode; -}; - export type DefaultizedAxisConfig = { [axisId: AxisId]: AxisDefaultized; }; @@ -73,39 +54,22 @@ export interface UseChartCartesianAxisParameters { * If not provided, a default axis config is used. * An array of [[AxisConfig]] objects. */ - xAxis: AxisConfig[]; + xAxis?: MakeOptional, 'id'>[]; /** * The configuration of the y-axes. * If not provided, a default axis config is used. * An array of [[AxisConfig]] objects. */ - yAxis: AxisConfig[]; + yAxis?: MakeOptional, 'id'>[]; + dataset?: DatasetType; } export type UseChartCartesianAxisDefaultizedParameters = UseChartCartesianAxisParameters & {}; export interface UseChartCartesianAxisState { cartesianAxis: { - x: { - /** - * Mapping from x-axis key to scaling configuration. - */ - axis: DefaultizedAxisConfig; - /** - * The x-axes IDs sorted by order they got provided. - */ - axisIds: AxisId[]; - }; - y: { - /** - * Mapping from y-axis key to scaling configuration. - */ - axis: DefaultizedAxisConfig; - /** - * The y-axes IDs sorted by order they got provided. - */ - axisIds: AxisId[]; - }; + x: AxisConfig[]; + y: AxisConfig[]; }; } @@ -116,13 +80,14 @@ export type ExtremumFilter = ( export interface UseChartCartesianAxisInstance {} -export type UseChartCartesianAxisSignature = ChartPluginSignature<{ - params: UseChartCartesianAxisParameters; - defaultizedParams: UseChartCartesianAxisDefaultizedParameters; - state: UseChartCartesianAxisState; - // instance: UseChartCartesianAxisInstance; - dependencies: [UseChartSeriesSignature]; -}>; +export type UseChartCartesianAxisSignature = + ChartPluginSignature<{ + params: UseChartCartesianAxisParameters; + defaultizedParams: UseChartCartesianAxisDefaultizedParameters; + state: UseChartCartesianAxisState; + // instance: UseChartCartesianAxisInstance; + dependencies: [UseChartSeriesSignature]; + }>; export type ZoomData = { axisId: AxisId; start: number; end: number }; diff --git a/packages/x-charts/src/internals/plugins/models/plugin.ts b/packages/x-charts/src/internals/plugins/models/plugin.ts index f762b8e6f409..94734314f2e1 100644 --- a/packages/x-charts/src/internals/plugins/models/plugin.ts +++ b/packages/x-charts/src/internals/plugins/models/plugin.ts @@ -7,12 +7,21 @@ import { ChartSeriesConfig } from './seriesConfig'; export interface ChartPluginOptions { instance: ChartUsedInstance; params: ChartUsedDefaultizedParams; + models: ChartUsedControlModels; store: ChartUsedStore; svgRef: React.RefObject; plugins: ChartPlugin[]; seriesConfig: ChartSeriesConfig; } +type ChartControlModelsInitializer = { + [TControlled in keyof TSignature['models']]: { + getDefaultValue: ( + params: TSignature['defaultizedParams'], + ) => Exclude; + }; +}; + type ChartResponse = OptionalIfEmpty< 'publicAPI', TSignature['publicAPI'] @@ -26,6 +35,7 @@ export type ChartPluginSignature< instance?: {}; publicAPI?: {}; state?: {}; + modelNames?: keyof T['defaultizedParams']; dependencies?: readonly ChartAnyPluginSignature[]; optionalDependencies?: readonly ChartAnyPluginSignature[]; }, @@ -35,6 +45,13 @@ export type ChartPluginSignature< instance: T extends { instance: {} } ? T['instance'] : {}; state: T extends { state: {} } ? T['state'] : {}; publicAPI: T extends { publicAPI: {} } ? T['publicAPI'] : {}; + models: T extends { defaultizedParams: {}; modelNames: keyof T['defaultizedParams'] } + ? { + [TControlled in T['modelNames']]-?: ChartControlModel< + Exclude + >; + } + : {}; dependencies: T extends { dependencies: Array } ? T['dependencies'] : []; optionalDependencies: T extends { optionalDependencies: Array } ? T['optionalDependencies'] @@ -45,6 +62,7 @@ export type ChartAnyPluginSignature = { state: any; instance: any; params: any; + models: any; defaultizedParams: any; dependencies: any; optionalDependencies: any; @@ -77,6 +95,20 @@ export type ChartUsedInstance = $$signature: TSignature; }; +export interface ChartControlModel { + name: string; + value: TValue; + setControlledValue: (value: TValue | ((prevValue: TValue) => TValue)) => void; +} + +type RemoveSetValue>> = { + [K in keyof Models]: Omit; +}; + +export type ChartUsedControlModels = + TSignature['models'] & + RemoveSetValue, 'models'>>; + export type ChartUsedStore = ChartStore< [TSignature, ...TSignature['dependencies']] >; @@ -88,6 +120,7 @@ export type ChartPlugin = { currentState: MergeSignaturesProperty, 'state'>, seriesConfig: ChartSeriesConfig, ) => TSignature['state']; + models?: ChartControlModelsInitializer; params: Record; getDefaultizedParams?: (options: { params: ChartUsedParams; diff --git a/packages/x-charts/src/internals/store/useChartModels.ts b/packages/x-charts/src/internals/store/useChartModels.ts new file mode 100644 index 000000000000..532e5e709d7a --- /dev/null +++ b/packages/x-charts/src/internals/store/useChartModels.ts @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { + ChartAnyPluginSignature, + ConvertSignaturesIntoPlugins, + MergeSignaturesProperty, + ChartPlugin, +} from '../plugins/models'; +import { ChartCorePluginSignatures } from '../plugins/corePlugins'; + +/** + * Implements the same behavior as `useControlled` but for several models. + * The controlled models are never stored in the state, and the state is only updated if the model is not controlled. + */ +export const useChartModels = ( + plugins: ConvertSignaturesIntoPlugins, + props: MergeSignaturesProperty, +) => { + type DefaultizedParams = MergeSignaturesProperty; + + const modelsRef = React.useRef<{ + [modelName: string]: { + getDefaultValue: (params: DefaultizedParams) => any; + isControlled: boolean; + }; + }>({}); + + const [modelsState, setModelsState] = React.useState<{ [modelName: string]: any }>(() => { + const initialState: { [modelName: string]: any } = {}; + + plugins.forEach((plugin: ChartPlugin) => { + if (plugin.models) { + Object.entries(plugin.models).forEach(([modelName, modelInitializer]) => { + modelsRef.current[modelName] = { + isControlled: props[modelName as keyof DefaultizedParams] !== undefined, + getDefaultValue: modelInitializer.getDefaultValue, + }; + initialState[modelName] = modelInitializer.getDefaultValue(props); + }); + } + }); + + return initialState; + }); + + const models = Object.fromEntries( + Object.entries(modelsRef.current).map(([modelName, model]) => { + const value = props[modelName as keyof DefaultizedParams] ?? modelsState[modelName]; + + return [ + modelName, + { + value, + setControlledValue: (newValue: any) => { + if (!model.isControlled) { + setModelsState((prevState) => ({ + ...prevState, + [modelName]: newValue, + })); + } + }, + }, + ]; + }), + ) as MergeSignaturesProperty; + + // We know that `modelsRef` do not vary across renders. + if (process.env.NODE_ENV !== 'production') { + Object.entries(modelsRef.current).forEach(([modelName, model]) => { + const controlled = props[modelName as keyof DefaultizedParams]; + const newDefaultValue = model.getDefaultValue(props); + + /* eslint-disable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps, react-compiler/react-compiler */ + React.useEffect(() => { + if (model.isControlled !== (controlled !== undefined)) { + console.error( + [ + `MUI X: A component is changing the ${ + model.isControlled ? '' : 'un' + }controlled ${modelName} state of Chart to be ${ + model.isControlled ? 'un' : '' + }controlled.`, + 'Elements should not switch from uncontrolled to controlled (or vice versa).', + `Decide between using a controlled or uncontrolled ${modelName} ` + + 'element for the lifetime of the component.', + "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", + 'More info: https://fb.me/react-controlled-components', + ].join('\n'), + ); + } + }, [controlled]); + + const { current: defaultValue } = React.useRef(newDefaultValue); + + React.useEffect(() => { + if (!model.isControlled && defaultValue !== newDefaultValue) { + console.error( + [ + `MUI X: A component is changing the default ${modelName} state of an uncontrolled Chart after being initialized. ` + + `To suppress this warning opt to use a controlled Chart.`, + ].join('\n'), + ); + } + }, [JSON.stringify(newDefaultValue)]); + }); + } + /* eslint-enable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */ + + return models; +}; diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index 981f61ff7ce4..915a889c7ecc 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -1,4 +1,5 @@ import * as React from 'react'; +import useId from '@mui/utils/useId'; import { ChartStore } from '../plugins/utils/ChartStore'; import { ChartAnyPluginSignature, @@ -14,6 +15,7 @@ import { UseChartInteractionState } from '../plugins/featurePlugins/useChartInte import { extractPluginParamsFromProps } from './extractPluginParamsFromProps'; import { ChartSeriesType } from '../../models/seriesType/config'; import { ChartSeriesConfig } from '../plugins/models/seriesConfig'; +import { useChartModels } from './useChartModels'; export function useChartApiInitialization( inputApiRef: React.MutableRefObject | undefined, @@ -47,6 +49,8 @@ export function useCharts< ...TSignatures, ]; + const chartId = useId(); + const plugins = React.useMemo( () => [ @@ -60,7 +64,9 @@ export function useCharts< plugins, props, }); + pluginParams.id = pluginParams.id ?? chartId; + const models = useChartModels(plugins, pluginParams); const instanceRef = React.useRef({} as ChartInstance); const instance = instanceRef.current as ChartInstance; const publicAPI = useChartApiInitialization>(props.apiRef); @@ -99,6 +105,7 @@ export function useCharts< store: storeRef.current as ChartStore, svgRef: innerSvgRef, seriesConfig, + models, }); if (pluginResponse.publicAPI) { From 2c345c05a1f3d398f7406be948eac1ee32aad74c Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 11 Dec 2024 10:43:21 +0100 Subject: [PATCH 10/32] scripts --- docs/pages/x/api/charts/bar-chart-pro.json | 4 +- docs/pages/x/api/charts/bar-chart.json | 4 +- .../x/api/charts/chart-container-pro.json | 10 +- docs/pages/x/api/charts/chart-container.json | 10 +- .../x/api/charts/chart-data-provider.json | 62 +---- docs/pages/x/api/charts/gauge-container.json | 8 +- docs/pages/x/api/charts/gauge.json | 8 +- docs/pages/x/api/charts/heatmap.json | 4 +- docs/pages/x/api/charts/line-chart-pro.json | 4 +- docs/pages/x/api/charts/line-chart.json | 4 +- docs/pages/x/api/charts/pie-chart.json | 4 +- .../pages/x/api/charts/scatter-chart-pro.json | 4 +- docs/pages/x/api/charts/scatter-chart.json | 4 +- docs/pages/x/api/charts/spark-line-chart.json | 1 + .../charts/bar-chart-pro/bar-chart-pro.json | 3 + .../api-docs/charts/bar-chart/bar-chart.json | 3 + .../chart-container-pro.json | 6 +- .../chart-container/chart-container.json | 6 +- .../chart-data-provider.json | 17 +- .../gauge-container/gauge-container.json | 4 + .../api-docs/charts/gauge/gauge.json | 4 + .../api-docs/charts/heatmap/heatmap.json | 3 + .../charts/line-chart-pro/line-chart-pro.json | 3 + .../charts/line-chart/line-chart.json | 3 + .../api-docs/charts/pie-chart/pie-chart.json | 3 + .../scatter-chart-pro/scatter-chart-pro.json | 3 + .../charts/scatter-chart/scatter-chart.json | 3 + .../spark-line-chart/spark-line-chart.json | 3 + .../src/BarChartPro/BarChartPro.tsx | 7 +- .../ChartContainerPro/ChartContainerPro.tsx | 15 +- packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 7 +- .../src/LineChartPro/LineChartPro.tsx | 7 +- .../src/ScatterChartPro/ScatterChartPro.tsx | 7 +- .../useChartProCartesianAxis.ts | 1 - packages/x-charts/src/BarChart/BarChart.tsx | 7 +- packages/x-charts/src/BarChart/extremums.ts | 2 +- .../src/ChartContainer/ChartContainer.tsx | 15 +- .../x-charts/src/ChartsGrid/ChartsGrid.tsx | 4 +- .../src/ChartsTooltip/useAxisTooltip.tsx | 1 - .../src/ChartsTooltip/useItemTooltip.tsx | 6 +- packages/x-charts/src/Gauge/Gauge.tsx | 13 +- .../x-charts/src/Gauge/GaugeContainer.tsx | 27 ++- packages/x-charts/src/LineChart/LineChart.tsx | 19 +- packages/x-charts/src/LineChart/extremums.ts | 5 +- packages/x-charts/src/PieChart/PieChart.tsx | 7 +- .../src/ScatterChart/ScatterChart.tsx | 7 +- .../src/SparkLineChart/SparkLineChart.tsx | 6 + .../ChartDataProvider/ChartDataProvider.tsx | 228 ++---------------- scripts/x-charts-pro.exports.json | 3 + scripts/x-charts.exports.json | 3 + 50 files changed, 227 insertions(+), 365 deletions(-) diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index e6999eac514e..3cb114280eba 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -37,6 +37,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "layout": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'vertical'" @@ -50,8 +51,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onAxisClick": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/bar-chart.json b/docs/pages/x/api/charts/bar-chart.json index aa9385f93970..e90e8356ac65 100644 --- a/docs/pages/x/api/charts/bar-chart.json +++ b/docs/pages/x/api/charts/bar-chart.json @@ -37,6 +37,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "layout": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'vertical'" @@ -50,8 +51,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onAxisClick": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index 32ee3b1e532e..731804781339 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -1,9 +1,5 @@ { "props": { - "series": { - "type": { "name": "arrayOf", "description": "Array<object>" }, - "required": true - }, "colors": { "type": { "name": "union", "description": "Array<string>
| func" }, "default": "blueberryTwilightPalette" @@ -17,12 +13,12 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "margin": { "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onHighlightChange": { "type": { "name": "func" }, @@ -38,7 +34,7 @@ "describedArgs": ["zoomData"] } }, - "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, "skipAnimation": { "type": { "name": "bool" } }, "width": { "type": { "name": "number" } }, "xAxis": { diff --git a/docs/pages/x/api/charts/chart-container.json b/docs/pages/x/api/charts/chart-container.json index 3f592ff3b587..85a20d635844 100644 --- a/docs/pages/x/api/charts/chart-container.json +++ b/docs/pages/x/api/charts/chart-container.json @@ -1,9 +1,5 @@ { "props": { - "series": { - "type": { "name": "arrayOf", "description": "Array<object>" }, - "required": true - }, "colors": { "type": { "name": "union", "description": "Array<string>
| func" }, "default": "blueberryTwilightPalette" @@ -17,12 +13,12 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "margin": { "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onHighlightChange": { "type": { "name": "func" }, @@ -31,7 +27,7 @@ "describedArgs": ["highlightedItem"] } }, - "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, "skipAnimation": { "type": { "name": "bool" } }, "width": { "type": { "name": "number" } }, "xAxis": { diff --git a/docs/pages/x/api/charts/chart-data-provider.json b/docs/pages/x/api/charts/chart-data-provider.json index 001c5b9e16d9..2f7893bf38fe 100644 --- a/docs/pages/x/api/charts/chart-data-provider.json +++ b/docs/pages/x/api/charts/chart-data-provider.json @@ -1,56 +1,16 @@ { "props": { - "series": { - "type": { "name": "arrayOf", "description": "Array<object>" }, - "required": true - }, - "colors": { - "type": { "name": "union", "description": "Array<string>
| func" }, - "default": "blueberryTwilightPalette" - }, - "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "height": { "type": { "name": "number" } }, - "highlightedItem": { - "type": { - "name": "shape", - "description": "{ dataIndex?: number, seriesId?: number
| string }" - } - }, - "margin": { - "type": { - "name": "shape", - "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." - }, - "onHighlightChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(highlightedItem: HighlightItemData | null) => void", - "describedArgs": ["highlightedItem"] - } - }, - "plugins": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "skipAnimation": { "type": { "name": "bool" } }, - "width": { "type": { "name": "number" } }, - "xAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" - } - }, - "yAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelFontSize?: number, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickFontSize?: number, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" - } - }, - "zAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" - } - } + "colors": { "type": { "name": "any" }, "default": "blueberryTwilightPalette" }, + "dataset": { "type": { "name": "any" } }, + "height": { "type": { "name": "any" } }, + "highlightedItem": { "type": { "name": "any" } }, + "id": { "type": { "name": "any" } }, + "margin": { "type": { "name": "any" } }, + "onHighlightChange": { "type": { "name": "any" } }, + "series": { "type": { "name": "any" } }, + "skipAnimation": { "type": { "name": "any" } }, + "width": { "type": { "name": "any" } }, + "zAxis": { "type": { "name": "any" } } }, "name": "ChartDataProvider", "imports": [ diff --git a/docs/pages/x/api/charts/gauge-container.json b/docs/pages/x/api/charts/gauge-container.json index ad6e12601495..546197e72781 100644 --- a/docs/pages/x/api/charts/gauge-container.json +++ b/docs/pages/x/api/charts/gauge-container.json @@ -1,5 +1,9 @@ { "props": { + "colors": { + "type": { "name": "union", "description": "Array<string>
| func" }, + "default": "blueberryTwilightPalette" + }, "cornerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "0" @@ -9,6 +13,7 @@ "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, "endAngle": { "type": { "name": "number" }, "default": "360" }, "height": { "type": { "name": "number" } }, + "id": { "type": { "name": "string" } }, "innerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "'80%'" @@ -17,8 +22,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "outerRadius": { "type": { "name": "union", "description": "number
| string" }, diff --git a/docs/pages/x/api/charts/gauge.json b/docs/pages/x/api/charts/gauge.json index 6a6dbc35e3df..177bdfb34ad0 100644 --- a/docs/pages/x/api/charts/gauge.json +++ b/docs/pages/x/api/charts/gauge.json @@ -1,5 +1,9 @@ { "props": { + "colors": { + "type": { "name": "union", "description": "Array<string>
| func" }, + "default": "blueberryTwilightPalette" + }, "cornerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "0" @@ -9,6 +13,7 @@ "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, "endAngle": { "type": { "name": "number" }, "default": "360" }, "height": { "type": { "name": "number" } }, + "id": { "type": { "name": "string" } }, "innerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "'80%'" @@ -17,8 +22,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "outerRadius": { "type": { "name": "union", "description": "number
| string" }, diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index 0e42547e3966..49c5f76badf3 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -35,6 +35,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -44,8 +45,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onAxisClick": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index da018ce78424..c64adbe51562 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -38,6 +38,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -47,8 +48,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onAreaClick": { "type": { "name": "func" } }, "onAxisClick": { diff --git a/docs/pages/x/api/charts/line-chart.json b/docs/pages/x/api/charts/line-chart.json index 6ecb8a0d4633..0915fe48dd08 100644 --- a/docs/pages/x/api/charts/line-chart.json +++ b/docs/pages/x/api/charts/line-chart.json @@ -38,6 +38,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -47,8 +48,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onAreaClick": { "type": { "name": "func" } }, "onAxisClick": { diff --git a/docs/pages/x/api/charts/pie-chart.json b/docs/pages/x/api/charts/pie-chart.json index d4b6bfe884d3..d12c4918cabb 100644 --- a/docs/pages/x/api/charts/pie-chart.json +++ b/docs/pages/x/api/charts/pie-chart.json @@ -18,13 +18,13 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "loading": { "type": { "name": "bool" }, "default": "false" }, "margin": { "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onHighlightChange": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index bca0f97741f7..e8351a1dbad0 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -37,6 +37,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -46,8 +47,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onHighlightChange": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/scatter-chart.json b/docs/pages/x/api/charts/scatter-chart.json index f573b3e0ab7f..f7337cc79ac8 100644 --- a/docs/pages/x/api/charts/scatter-chart.json +++ b/docs/pages/x/api/charts/scatter-chart.json @@ -37,6 +37,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -46,8 +47,7 @@ "type": { "name": "shape", "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - }, - "default": "object Depends on the charts type." + } }, "onHighlightChange": { "type": { "name": "func" }, diff --git a/docs/pages/x/api/charts/spark-line-chart.json b/docs/pages/x/api/charts/spark-line-chart.json index 683d2ce39d35..f7f0f7bf78e8 100644 --- a/docs/pages/x/api/charts/spark-line-chart.json +++ b/docs/pages/x/api/charts/spark-line-chart.json @@ -18,6 +18,7 @@ "description": "{ dataIndex?: number, seriesId?: number
| string }" } }, + "id": { "type": { "name": "string" } }, "margin": { "type": { "name": "shape", diff --git a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json index 6c9d9aca524b..9cc3519bbf28 100644 --- a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json +++ b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json @@ -27,6 +27,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "layout": { "description": "The direction of the bar elements." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." diff --git a/docs/translations/api-docs/charts/bar-chart/bar-chart.json b/docs/translations/api-docs/charts/bar-chart/bar-chart.json index f1214f5f990b..9af62108b49d 100644 --- a/docs/translations/api-docs/charts/bar-chart/bar-chart.json +++ b/docs/translations/api-docs/charts/bar-chart/bar-chart.json @@ -27,6 +27,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "layout": { "description": "The direction of the bar elements." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." diff --git a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json index 3adf5b2e91ce..efa8c876bb1e 100644 --- a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json +++ b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json @@ -14,6 +14,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." }, @@ -25,9 +28,6 @@ "description": "Callback fired when the zoom has changed.", "typeDescriptions": { "zoomData": "Updated zoom data." } }, - "plugins": { - "description": "An array of plugins defining how to preprocess data. If not provided, the container supports line, bar, scatter and pie charts." - }, "series": { "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." }, diff --git a/docs/translations/api-docs/charts/chart-container/chart-container.json b/docs/translations/api-docs/charts/chart-container/chart-container.json index 45f4bcacdeca..954410893680 100644 --- a/docs/translations/api-docs/charts/chart-container/chart-container.json +++ b/docs/translations/api-docs/charts/chart-container/chart-container.json @@ -14,6 +14,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." }, @@ -21,9 +24,6 @@ "description": "The callback fired when the highlighted item changes.", "typeDescriptions": { "highlightedItem": "The newly highlighted item." } }, - "plugins": { - "description": "An array of plugins defining how to preprocess data. If not provided, the container supports line, bar, scatter and pie charts." - }, "series": { "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." }, diff --git a/docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json b/docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json index 57a8f05201d9..0679bb83a3f8 100644 --- a/docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json +++ b/docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json @@ -11,16 +11,13 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." }, - "onHighlightChange": { - "description": "The callback fired when the highlighted item changes.", - "typeDescriptions": { "highlightedItem": "The newly highlighted item." } - }, - "plugins": { - "description": "An array of plugins defining how to preprocess data. If not provided, the container supports line, bar, scatter and pie charts." - }, + "onHighlightChange": { "description": "The callback fired when the highlighted item changes." }, "series": { "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." }, @@ -30,12 +27,6 @@ "width": { "description": "The width of the chart in px. If not defined, it takes the width of the parent element." }, - "xAxis": { - "description": "The configuration of the x-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "yAxis": { - "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} diff --git a/docs/translations/api-docs/charts/gauge-container/gauge-container.json b/docs/translations/api-docs/charts/gauge-container/gauge-container.json index 37908f418af5..29df208ed271 100644 --- a/docs/translations/api-docs/charts/gauge-container/gauge-container.json +++ b/docs/translations/api-docs/charts/gauge-container/gauge-container.json @@ -1,6 +1,7 @@ { "componentDescription": "", "propDescriptions": { + "colors": { "description": "Color palette used to colorize multiple series." }, "cornerRadius": { "description": "The radius applied to arc corners (similar to border radius). Set it to '50%' to get rounded arc." }, @@ -17,6 +18,9 @@ "height": { "description": "The height of the chart in px. If not defined, it takes the height of the parent element." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "innerRadius": { "description": "The radius between circle center and the beginning of the arc. Can be a number (in px) or a string with a percentage such as '50%'. The '100%' is the maximal radius that fit into the drawing area." }, diff --git a/docs/translations/api-docs/charts/gauge/gauge.json b/docs/translations/api-docs/charts/gauge/gauge.json index 4833ce77d746..b1b19127feaa 100644 --- a/docs/translations/api-docs/charts/gauge/gauge.json +++ b/docs/translations/api-docs/charts/gauge/gauge.json @@ -1,6 +1,7 @@ { "componentDescription": "", "propDescriptions": { + "colors": { "description": "Color palette used to colorize multiple series." }, "cornerRadius": { "description": "The radius applied to arc corners (similar to border radius). Set it to '50%' to get rounded arc." }, @@ -17,6 +18,9 @@ "height": { "description": "The height of the chart in px. If not defined, it takes the height of the parent element." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "innerRadius": { "description": "The radius between circle center and the beginning of the arc. Can be a number (in px) or a string with a percentage such as '50%'. The '100%' is the maximal radius that fit into the drawing area." }, diff --git a/docs/translations/api-docs/charts/heatmap/heatmap.json b/docs/translations/api-docs/charts/heatmap/heatmap.json index 8db3fec541fc..e74feb7819de 100644 --- a/docs/translations/api-docs/charts/heatmap/heatmap.json +++ b/docs/translations/api-docs/charts/heatmap/heatmap.json @@ -17,6 +17,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json index 827d16ab4cd1..e247d0464564 100644 --- a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json +++ b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json @@ -29,6 +29,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/line-chart/line-chart.json b/docs/translations/api-docs/charts/line-chart/line-chart.json index efd9317f9eb4..513369329503 100644 --- a/docs/translations/api-docs/charts/line-chart/line-chart.json +++ b/docs/translations/api-docs/charts/line-chart/line-chart.json @@ -29,6 +29,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/pie-chart/pie-chart.json b/docs/translations/api-docs/charts/pie-chart/pie-chart.json index 981a35075a12..3e7f32b845fa 100644 --- a/docs/translations/api-docs/charts/pie-chart/pie-chart.json +++ b/docs/translations/api-docs/charts/pie-chart/pie-chart.json @@ -15,6 +15,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "loading": { "description": "If true, a loading overlay is displayed." }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." diff --git a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json index 5d1e1a64cfe9..d62674842fb5 100644 --- a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json +++ b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json @@ -26,6 +26,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json b/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json index 85123d0e7102..960dee7bfee1 100644 --- a/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json +++ b/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json @@ -26,6 +26,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json b/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json index 342905c4fba4..c4182f4cc964 100644 --- a/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json +++ b/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json @@ -18,6 +18,9 @@ "highlightedItem": { "description": "The item currently highlighted. Turns highlighting into a controlled prop." }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." }, diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 2c08c454d575..eb09aca44919 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -190,6 +190,11 @@ BarChartPro.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The direction of the bar elements. * @default 'vertical' @@ -210,7 +215,6 @@ BarChartPro.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -274,6 +278,7 @@ BarChartPro.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Indicate which axis to display the top of the charts. diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index f6f9ff734c34..a35d0b7a4a91 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -65,11 +65,15 @@ ChartContainerPro.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -89,17 +93,13 @@ ChartContainerPro.propTypes = { * @param {ZoomData[]} zoomData Updated zoom data. */ onZoomChange: PropTypes.func, - /** - * An array of plugins defining how to preprocess data. - * If not provided, the container supports line, bar, scatter and pie charts. - */ - plugins: PropTypes.arrayOf(PropTypes.object), + plugins: PropTypes.arrayOf(PropTypes.func.isRequired), /** * The array of series to display. * Each type of series has its own specificity. * Please refer to the appropriate docs page to learn more about it. */ - series: PropTypes.arrayOf(PropTypes.object).isRequired, + series: PropTypes.arrayOf(PropTypes.object), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. @@ -110,6 +110,7 @@ ChartContainerPro.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The width of the chart in px. If not defined, it takes the width of the parent element. diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index 7f72b1acbe20..7446f93b3537 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -242,6 +242,11 @@ Heatmap.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -257,7 +262,6 @@ Heatmap.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -304,6 +308,7 @@ Heatmap.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The configuration of the tooltip. diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index 82b9a6d5c5bc..c44a3bcd524e 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -261,6 +261,11 @@ LineChartPro.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -276,7 +281,6 @@ LineChartPro.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -346,6 +350,7 @@ LineChartPro.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Indicate which axis to display the top of the charts. diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index b8fd1543b725..7e48283484d8 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -135,6 +135,11 @@ ScatterChartPro.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -150,7 +155,6 @@ ScatterChartPro.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -207,6 +211,7 @@ ScatterChartPro.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Indicate which axis to display the top of the charts. diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts index fcccf5f9ca40..61b534c05da2 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts @@ -36,7 +36,6 @@ export const useChartProCartesianAxis: ChartPlugin { if (direction === 'x') { diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 62b3cbea36c9..2d5f66e5a774 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -85,11 +85,15 @@ ChartContainer.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -103,17 +107,13 @@ ChartContainer.propTypes = { * @param {HighlightItemData | null} highlightedItem The newly highlighted item. */ onHighlightChange: PropTypes.func, - /** - * An array of plugins defining how to preprocess data. - * If not provided, the container supports line, bar, scatter and pie charts. - */ - plugins: PropTypes.arrayOf(PropTypes.object), + plugins: PropTypes.arrayOf(PropTypes.func.isRequired), /** * The array of series to display. * Each type of series has its own specificity. * Please refer to the appropriate docs page to learn more about it. */ - series: PropTypes.arrayOf(PropTypes.object).isRequired, + series: PropTypes.arrayOf(PropTypes.object), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. @@ -124,6 +124,7 @@ ChartContainer.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The width of the chart in px. If not defined, it takes the width of the parent element. diff --git a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx index d4195bad5b19..0c5161fed9dd 100644 --- a/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx +++ b/packages/x-charts/src/ChartsGrid/ChartsGrid.tsx @@ -49,8 +49,8 @@ function ChartsGrid(inProps: ChartsGridProps) { const drawingArea = useDrawingArea(); const { vertical, horizontal, ...other } = props; - const { xAxis, xAxisIds } = useXAxes(); - const { yAxis, yAxisIds } = useYAxes(); + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); const classes = useUtilityClasses(props); diff --git a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx index 5ce01f222094..c62965daaddc 100644 --- a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx @@ -49,7 +49,6 @@ export function useAxisTooltip(): null | UseAxisTooltipReturnValue { const series = useSeries(); - const { xAxis } = useXAxes(); const { yAxis } = useYAxes(); diff --git a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx index 51620532db25..9afdee9f4564 100644 --- a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx @@ -30,9 +30,9 @@ export function useItemTooltip(): null | UseItemToolt const series = useSeries(); - const { xAxis, xAxisIds } = useXAxes(); - const { yAxis, yAxisIds } = useYAxes(); - + const { xAxis, xAxisIds } = useXAxes(); + const { yAxis, yAxisIds } = useYAxes(); + const { zAxis, zAxisIds } = React.useContext(ZAxisContext); const colorProcessors = useColorProcessor(); diff --git a/packages/x-charts/src/Gauge/Gauge.tsx b/packages/x-charts/src/Gauge/Gauge.tsx index c169d1251f9e..d3dff37a4fda 100644 --- a/packages/x-charts/src/Gauge/Gauge.tsx +++ b/packages/x-charts/src/Gauge/Gauge.tsx @@ -48,6 +48,11 @@ Gauge.propTypes = { children: PropTypes.node, classes: PropTypes.object, className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), /** * The radius applied to arc corners (similar to border radius). * Set it to '50%' to get rounded arc. @@ -66,6 +71,7 @@ Gauge.propTypes = { * The '100%' is the height the drawing area. */ cy: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + dataset: PropTypes.arrayOf(PropTypes.object), desc: PropTypes.string, /** * If `true`, the charts will not listen to the mouse move event. @@ -82,6 +88,11 @@ Gauge.propTypes = { * The height of the chart in px. If not defined, it takes the height of the parent element. */ height: PropTypes.number, + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The radius between circle center and the beginning of the arc. * Can be a number (in px) or a string with a percentage such as '50%'. @@ -93,7 +104,6 @@ Gauge.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -119,6 +129,7 @@ Gauge.propTypes = { PropTypes.object, ]), text: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The value of the gauge. diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index 63f206e16d21..f07cd3da3428 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -9,18 +9,10 @@ import { MergeSignaturesProperty } from '../internals/plugins/models'; import { ChartCorePluginSignatures } from '../internals/plugins/corePlugins'; export interface GaugeContainerProps - extends Omit, - MergeSignaturesProperty, + extends Omit, + Omit, 'series'>, Omit, - React.SVGProps { - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width?: number; - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height?: number; + Omit, 'width' | 'height'> { children?: React.ReactNode; } @@ -100,6 +92,11 @@ GaugeContainer.propTypes = { // ---------------------------------------------------------------------- children: PropTypes.node, className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), /** * The radius applied to arc corners (similar to border radius). * Set it to '50%' to get rounded arc. @@ -118,6 +115,7 @@ GaugeContainer.propTypes = { * The '100%' is the height the drawing area. */ cy: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + dataset: PropTypes.arrayOf(PropTypes.object), desc: PropTypes.string, /** * If `true`, the charts will not listen to the mouse move event. @@ -134,6 +132,11 @@ GaugeContainer.propTypes = { * The height of the chart in px. If not defined, it takes the height of the parent element. */ height: PropTypes.number, + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The radius between circle center and the beginning of the arc. * Can be a number (in px) or a string with a percentage such as '50%'. @@ -145,7 +148,6 @@ GaugeContainer.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -170,6 +172,7 @@ GaugeContainer.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The value of the gauge. diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 6cd7ead06de8..34dad3e4df0b 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -54,14 +54,14 @@ export interface LineChartSlotProps export interface LineChartProps extends Omit, - // Omit, + Omit, Omit, ChartsOnAxisClickHandlerProps { - // /** - // * The series to display in the line chart. - // * An array of [[LineSeriesType]] objects. - // */ - // series: MakeOptional[]; + /** + * The series to display in the line chart. + * An array of [[LineSeriesType]] objects. + */ + series: MakeOptional[]; /** * Option to display a cartesian grid in the background. */ @@ -239,6 +239,11 @@ LineChart.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -254,7 +259,6 @@ LineChart.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -318,6 +322,7 @@ LineChart.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Indicate which axis to display the top of the charts. diff --git a/packages/x-charts/src/LineChart/extremums.ts b/packages/x-charts/src/LineChart/extremums.ts index cda6234e4fec..81df7f8fe822 100644 --- a/packages/x-charts/src/LineChart/extremums.ts +++ b/packages/x-charts/src/LineChart/extremums.ts @@ -1,4 +1,7 @@ -import { CartesianExtremumFilter, CartesianExtremumGetter } from "../internals/plugins/models/seriesConfig/extremumGetter.types"; +import { + CartesianExtremumFilter, + CartesianExtremumGetter, +} from '../internals/plugins/models/seriesConfig/extremumGetter.types'; export const getExtremumX: CartesianExtremumGetter<'line'> = (params) => { const { axis } = params; diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index 77bd0de044ae..02c5bceb7cf4 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -173,6 +173,11 @@ PieChart.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * If `true`, a loading overlay is displayed. * @default false @@ -182,7 +187,6 @@ PieChart.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -225,6 +229,7 @@ PieChart.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The width of the chart in px. If not defined, it takes the width of the parent element. diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index 3ccd27d56903..7da8c41de642 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -207,6 +207,11 @@ ScatterChart.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -222,7 +227,6 @@ ScatterChart.propTypes = { * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ margin: PropTypes.shape({ bottom: PropTypes.number, @@ -273,6 +277,7 @@ ScatterChart.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Indicate which axis to display the top of the charts. diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 53498f3c4c10..c50df74a9662 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -285,6 +285,11 @@ SparkLineChart.propTypes = { dataIndex: PropTypes.number, seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, /** * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. @@ -345,6 +350,7 @@ SparkLineChart.propTypes = { PropTypes.func, PropTypes.object, ]), + theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * Formatter used by the tooltip. diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index f3fa5c2dadfc..7eacee188658 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -87,251 +87,57 @@ ChartDataProvider.propTypes = { * Color palette used to colorize multiple series. * @default blueberryTwilightPalette */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), + colors: PropTypes.any, /** * An array of objects that can be used to populate series and axes data using their `dataKey` property. */ - dataset: PropTypes.arrayOf(PropTypes.object), + dataset: PropTypes.any, /** * The height of the chart in px. If not defined, it takes the height of the parent element. */ - height: PropTypes.number, + height: PropTypes.any, /** * The item currently highlighted. Turns highlighting into a controlled prop. */ - highlightedItem: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - }), + highlightedItem: PropTypes.any, + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.any, /** * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - * @default object Depends on the charts type. */ - margin: PropTypes.shape({ - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - top: PropTypes.number, - }), + margin: PropTypes.any, /** * The callback fired when the highlighted item changes. * * @param {HighlightItemData | null} highlightedItem The newly highlighted item. */ - onHighlightChange: PropTypes.func, - /** - * An array of plugins defining how to preprocess data. - * If not provided, the container supports line, bar, scatter and pie charts. - */ - plugins: PropTypes.arrayOf(PropTypes.object), + onHighlightChange: PropTypes.any, + plugins: PropTypes.object, /** * The array of series to display. * Each type of series has its own specificity. * Please refer to the appropriate docs page to learn more about it. */ - series: PropTypes.arrayOf(PropTypes.object).isRequired, + series: PropTypes.any, /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. */ - skipAnimation: PropTypes.bool, + skipAnimation: PropTypes.any, + theme: PropTypes.any, /** * The width of the chart in px. If not defined, it takes the width of the parent element. */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelFontSize: PropTypes.number, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickFontSize: PropTypes.number, - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelFontSize: PropTypes.number, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickFontSize: PropTypes.number, - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), + width: PropTypes.any, /** * The configuration of the z-axes. */ - zAxis: PropTypes.arrayOf( - PropTypes.shape({ - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - id: PropTypes.string, - max: PropTypes.number, - min: PropTypes.number, - }), - ), + zAxis: PropTypes.any, } as any; export { ChartDataProvider }; diff --git a/scripts/x-charts-pro.exports.json b/scripts/x-charts-pro.exports.json index 2404d9305ef6..03bfb2878b6e 100644 --- a/scripts/x-charts-pro.exports.json +++ b/scripts/x-charts-pro.exports.json @@ -57,6 +57,7 @@ { "name": "ChartContainerProProps", "kind": "Interface" }, { "name": "ChartDataProvider", "kind": "Function" }, { "name": "ChartDataProviderProps", "kind": "TypeAlias" }, + { "name": "ChartDrawingArea", "kind": "TypeAlias" }, { "name": "ChartsAxis", "kind": "Function" }, { "name": "ChartsAxisClasses", "kind": "Interface" }, { "name": "ChartsAxisClassKey", "kind": "TypeAlias" }, @@ -305,9 +306,11 @@ { "name": "UseItemTooltipReturnValue", "kind": "Interface" }, { "name": "useMouseTracker", "kind": "Function" }, { "name": "useSvgRef", "kind": "Function" }, + { "name": "useXAxes", "kind": "Function" }, { "name": "useXAxis", "kind": "Function" }, { "name": "useXColorScale", "kind": "Function" }, { "name": "useXScale", "kind": "Function" }, + { "name": "useYAxes", "kind": "Function" }, { "name": "useYAxis", "kind": "Function" }, { "name": "useYColorScale", "kind": "Function" }, { "name": "useYScale", "kind": "Function" }, diff --git a/scripts/x-charts.exports.json b/scripts/x-charts.exports.json index 4081f5bdcb11..65d49059e2f9 100644 --- a/scripts/x-charts.exports.json +++ b/scripts/x-charts.exports.json @@ -55,6 +55,7 @@ { "name": "ChartContainerProps", "kind": "Interface" }, { "name": "ChartDataProvider", "kind": "Function" }, { "name": "ChartDataProviderProps", "kind": "TypeAlias" }, + { "name": "ChartDrawingArea", "kind": "TypeAlias" }, { "name": "ChartsAxis", "kind": "Function" }, { "name": "ChartsAxisClasses", "kind": "Interface" }, { "name": "ChartsAxisClassKey", "kind": "TypeAlias" }, @@ -291,9 +292,11 @@ { "name": "UseItemTooltipReturnValue", "kind": "Interface" }, { "name": "useMouseTracker", "kind": "Function" }, { "name": "useSvgRef", "kind": "Function" }, + { "name": "useXAxes", "kind": "Function" }, { "name": "useXAxis", "kind": "Function" }, { "name": "useXColorScale", "kind": "Function" }, { "name": "useXScale", "kind": "Function" }, + { "name": "useYAxes", "kind": "Function" }, { "name": "useYAxis", "kind": "Function" }, { "name": "useYColorScale", "kind": "Function" }, { "name": "useYScale", "kind": "Function" }, From efdc03075b8943ab6ecb4ea8031be31cbd82eb99 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 11 Dec 2024 15:52:01 +0100 Subject: [PATCH 11/32] WIP --- .../src/BarChartPro/BarChartPro.tsx | 4 +- .../useChartContainerProProps.ts | 11 +- .../src/LineChartPro/LineChartPro.tsx | 8 +- .../ChartDataProviderPro.tsx | 15 +- .../src/context/ZoomProvider/Zoom.types.ts | 151 --------- .../context/ZoomProvider/defaultizeZoom.ts | 46 --- .../ZoomProvider/initializeZoomData.ts | 5 +- .../src/context/ZoomProvider/useSetupPan.ts | 289 +++++++++--------- .../src/context/ZoomProvider/useSetupZoom.ts | 94 ++++-- .../src/context/ZoomProvider/useZoom.ts | 23 +- .../defaultizeAxis.ts | 31 -- .../getAxisExtremum.ts | 70 ----- .../plugins/useChartProCartesianAxis/index.ts | 6 - .../useChartProCartesianAxis.selectors.ts | 10 - .../useChartProCartesianAxis.ts | 120 -------- .../useChartProCartesianAxis.types.ts | 154 ---------- .../plugins/useChartProCartesianAxis/zoom.ts | 23 -- .../defaultizeZoom.ts | 9 +- .../plugins/useChartProZoom/index.ts | 2 + .../useChartProZoom.selectors.ts | 15 + .../useChartProZoom/useChartProZoom.ts | 70 +++++ .../useChartProZoom/useChartProZoom.types.ts | 59 ++++ .../useChartProZoom.utils.ts} | 3 +- .../plugins/useChartProZoom/zoom.types.ts | 53 ++++ .../x-charts-pro/src/typeOverloads/modules.ts | 12 +- packages/x-charts-pro/tsconfig.json | 2 +- packages/x-charts/src/internals/index.ts | 2 +- .../corePlugins/useChartSeries/index.ts | 1 + .../useChartCartesianAxis/computeAxisValue.ts | 40 +-- .../createAxisFilterMapper.ts | 41 ++- .../useChartCartesianAxis/index.ts | 8 +- .../useChartCartesianAxis.selectors.ts | 122 +++++++- .../useChartCartesianAxis.ts | 20 +- .../useChartCartesianAxis.types.ts | 54 ++-- .../useChartCartesianAxis/zoom.types.ts | 19 ++ .../src/internals/plugins/models/plugin.ts | 5 +- 36 files changed, 688 insertions(+), 909 deletions(-) delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/Zoom.types.ts delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/defaultizeZoom.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts delete mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts rename packages/x-charts-pro/src/internals/plugins/{useChartProCartesianAxis => useChartProZoom}/defaultizeZoom.ts (61%) create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProZoom/index.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts rename packages/x-charts-pro/src/internals/plugins/{useChartProCartesianAxis/useChartProCartesianAxis.utils.ts => useChartProZoom/useChartProZoom.utils.ts} (67%) create mode 100644 packages/x-charts-pro/src/internals/plugins/useChartProZoom/zoom.types.ts rename packages/{x-charts-pro/src/internals/plugins/useChartProCartesianAxis => x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis}/createAxisFilterMapper.ts (64%) create mode 100644 packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index eb09aca44919..1cb4f20cef46 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -14,11 +14,11 @@ import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useBarChartProps } from '@mui/x-charts/internals'; import { ChartContainerPro } from '../ChartContainerPro'; import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; -import { useZoom } from '../context/ZoomProvider/useZoom'; +import { useZoomIsInteracting } from '../context/ZoomProvider/useZoom'; import { ZoomProps } from '../context/ZoomProvider'; function BarChartPlotZoom(props: BarPlotProps) { - const { isInteracting } = useZoom(); + const isInteracting = useZoomIsInteracting(); return ; } diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index b8b898c95ef3..1ed9a64b2494 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -1,8 +1,13 @@ 'use client'; -import { useChartContainerProps, UseChartContainerPropsReturnValue } from '@mui/x-charts/internals'; +import { + useChartCartesianAxis, + useChartContainerProps, + UseChartContainerPropsReturnValue, +} from '@mui/x-charts/internals'; import * as React from 'react'; import type { ChartDataProviderProProps } from '../context/ChartDataProviderPro'; import type { ChartContainerProProps } from './ChartContainerPro'; +import { useChartProZoom } from '../internals/plugins/useChartProZoom'; export type UseChartContainerProPropsReturnValue = Omit< UseChartContainerPropsReturnValue, @@ -15,7 +20,7 @@ export const useChartContainerProProps = ( props: ChartContainerProProps, ref: React.Ref, ): UseChartContainerProPropsReturnValue => { - const { zoom, onZoomChange, ...baseProps } = props; + const { zoom, onZoomChange, plugins, ...baseProps } = props; const chartDataProviderProProps: Pick = { zoom, @@ -31,6 +36,8 @@ export const useChartContainerProProps = ( chartDataProviderProProps: { ...chartDataProviderProps, ...chartDataProviderProProps, + // eslint-disable-next-line react-compiler/react-compiler + plugins: [useChartCartesianAxis, useChartProZoom], }, chartsSurfaceProps, children, diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index c44a3bcd524e..88e6d6986acd 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -23,11 +23,11 @@ import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useLineChartProps } from '@mui/x-charts/internals'; import { ChartContainerPro } from '../ChartContainerPro'; import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; -import { useZoom } from '../context/ZoomProvider/useZoom'; +import { useZoomIsInteracting } from '../context/ZoomProvider/useZoom'; import { ZoomProps } from '../context/ZoomProvider'; function AreaPlotZoom(props: AreaPlotProps) { - const { isInteracting } = useZoom(); + const isInteracting = useZoomIsInteracting(); return ; } @@ -60,7 +60,7 @@ AreaPlotZoom.propTypes = { } as any; function LinePlotZoom(props: LinePlotProps) { - const { isInteracting } = useZoom(); + const isInteracting = useZoomIsInteracting(); return ; } @@ -93,7 +93,7 @@ LinePlotZoom.propTypes = { } as any; function MarkPlotZoom(props: MarkPlotProps) { - const { isInteracting } = useZoom(); + const isInteracting = useZoomIsInteracting(); return ; } diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx index 9998c56009bb..876843e5c6f3 100644 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx +++ b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx @@ -1,16 +1,23 @@ 'use client'; import * as React from 'react'; -import { ChartDataProviderProps, AnimationProvider, ChartProvider } from '@mui/x-charts/internals'; +import { + ChartDataProviderProps, + AnimationProvider, + ChartProvider, + UseChartCartesianAxisSignature, +} from '@mui/x-charts/internals'; import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; import { getReleaseInfo } from '../../internals/utils/releaseInfo'; import { ZoomProps } from '../ZoomProvider'; import { useChartContainerProProps } from './useChartDataProviderProProps'; -import { useChartProCartesianAxis } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis'; +import { UseChartProZoomSignature } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; const releaseInfo = getReleaseInfo(); -export interface ChartDataProviderProProps extends ChartDataProviderProps<[UseCa]>, ZoomProps {} +export interface ChartDataProviderProProps + extends ChartDataProviderProps<[UseChartCartesianAxisSignature, UseChartProZoomSignature]>, + ZoomProps {} function ChartDataProviderPro(props: ChartDataProviderProProps) { const { @@ -24,7 +31,7 @@ function ChartDataProviderPro(props: ChartDataProviderProProps) { useLicenseVerifier('x-charts-pro', releaseInfo); return ( - + {children} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/Zoom.types.ts b/packages/x-charts-pro/src/context/ZoomProvider/Zoom.types.ts deleted file mode 100644 index 4943a6750f02..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/Zoom.types.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { AxisId } from '@mui/x-charts/internals'; - -export type ZoomProviderProps = { - children: React.ReactNode; - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis?: AxisConfigForZoom[]; - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis?: AxisConfigForZoom[]; -} & ZoomProps; - -/** - * Represents the state of the ZoomProvider. - */ -export type ZoomState = { - /** - * Whether zooming is enabled. - */ - isZoomEnabled: boolean; - /** - * Whether panning is enabled. - */ - isPanEnabled: boolean; - /** - * The zoom options for each axis. - */ - options: Record; - /** - * The zoom data for each axis - * @default [] - */ - zoomData: ZoomData[]; - /** - * Set the zoom data for each axis. - * @param {ZoomData[]} zoomData The new zoom data. - */ - setZoomData: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void; - /** - * Whether the user is currently interacting with the chart. - * This is useful to prevent animations from running while the user is interacting. - */ - isInteracting: boolean; - /** - * Set the interaction state of the chart. - * @param {boolean} isInteracting The new interaction state. - */ - setIsInteracting: (isInteracting: boolean) => void; -}; - -export type ZoomOptions = { - /** - * The starting percentage of the zoom range. In the range of 0 to 100. - * - * @default 0 - */ - minStart?: number; - /** - * The ending percentage of the zoom range. In the range of 0 to 100. - * - * @default 100 - */ - maxEnd?: number; - /** - * The step size of the zooming function. Defines the granularity of the zoom. - * - * @default 5 - */ - step?: number; - /** - * Restricts the minimum span size in the range of 0 to 100. - * - * If the span size is smaller than the minSpan, the span will be resized to the minSpan. - * - * @default 10 - */ - minSpan?: number; - /** - * Restricts the maximum span size in the range of 0 to 100. - * - * If the span size is larger than the maxSpan, the span will be resized to the maxSpan. - * - * @default 100 - */ - maxSpan?: number; - /** - * Set to `false` to disable panning. Useful when you want to pan programmatically, - * or to show only a specific section of the chart. - * - * @default true - */ - panning?: boolean; - /** - * Defines how to filter the axis data when it is outside of the zoomed range of this axis. - * - * - `keep`: The data outside the zoomed range is kept. And the other axes will stay the same. - * - `discard`: The data outside the zoomed range is discarded for the other axes. - * The other axes will be adjusted to fit the zoomed range. - * - * @default 'keep' - */ - filterMode?: 'discard' | 'keep'; -}; - -export type ZoomData = { - /** - * The starting percentage of the zoom range. In the range of 0 to 100. - * - * @default 0 - */ - start: number; - /** - * The ending percentage of the zoom range. In the range of 0 to 100. - * - * @default 100 - */ - end: number; - /** - * The axis id that the zoom data belongs to. - */ - axisId: AxisId; -}; - -export type ZoomProps = { - /** - * The list of zoom data related to each axis. - */ - zoom?: ZoomData[]; - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange?: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void; -}; - -export type DefaultizedZoomOptions = Required & { - axisId: AxisId; - axisDirection: 'x' | 'y'; -}; - -export type AxisConfigForZoom = { - id: AxisId; - zoom?: ZoomOptions | boolean; -}; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/defaultizeZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/defaultizeZoom.ts deleted file mode 100644 index 4f4c558e82b1..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/defaultizeZoom.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { isDefined } from '@mui/x-charts/internals'; -import { AxisConfigForZoom, DefaultizedZoomOptions, ZoomOptions } from './Zoom.types'; - -const defaultZoomOptions: Required = { - minStart: 0, - maxEnd: 100, - step: 5, - minSpan: 10, - maxSpan: 100, - panning: true, - filterMode: 'keep', -}; - -export const defaultizeZoom = ( - axis: AxisConfigForZoom[] | undefined, - axisDirection: 'x' | 'y', -): DefaultizedZoomOptions[] => { - if (!axis) { - return []; - } - - const defaultized = axis - .map((v) => { - if (!v.zoom) { - return undefined; - } - - if (v.zoom === true) { - return { - axisId: v.id, - axisDirection, - ...defaultZoomOptions, - }; - } - - return { - axisId: v.id, - axisDirection, - ...defaultZoomOptions, - ...v.zoom, - }; - }) - .filter(isDefined); - - return defaultized; -}; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts b/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts index 454865c58648..101473a50f41 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts @@ -1,8 +1,7 @@ -import { ZoomState } from './Zoom.types'; +import { AxisId, DefaultizedZoomOption } from '@mui/x-charts/internals'; -// This function is used to initialize the zoom data when it is not provided by the user. // It is helpful to avoid the need to provide the possibly auto-generated id for each axis. -export const initializeZoomData = (options: ZoomState['options']) => { +export const initializeZoomData = (options: Record) => { return Object.values(options).map(({ axisId, minStart: start, maxEnd: end }) => ({ axisId, start, diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts index b7dc5212c60c..b972eda08b24 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts @@ -1,143 +1,154 @@ 'use client'; -import * as React from 'react'; -import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; - -import { getSVGPoint, useChartContext } from '@mui/x-charts/internals'; -import { useZoom } from './useZoom'; -import { ZoomData } from './Zoom.types'; +// import * as React from 'react'; +// import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; + +// import { +// AxisId, +// getSVGPoint, +// useChartContext, +// useSelector, +// useStore, +// } from '@mui/x-charts/internals'; + +// import { ZoomData } from './Zoom.types'; +// import { useZoomIsInteracting } from './useZoom'; +// import { selectorChartZoomOptions } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors'; +// import { UseChartProCartesianAxisSignature } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types'; export const useSetupPan = () => { - const { zoomData, setZoomData, setIsInteracting, isPanEnabled, options } = useZoom(); - const drawingArea = useDrawingArea(); - const { instance } = useChartContext(); - const svgRef = useSvgRef(); - - const isDraggingRef = React.useRef(false); - const touchStartRef = React.useRef<{ x: number; y: number; zoomData: ZoomData[] } | null>(null); - const eventCacheRef = React.useRef([]); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null || !isPanEnabled) { - return () => {}; - } - - const handlePan = (event: PointerEvent) => { - if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) { - return; - } - - if (touchStartRef.current == null) { - return; - } - - const point = getSVGPoint(element, event); - const movementX = point.x - touchStartRef.current.x; - const movementY = (point.y - touchStartRef.current.y) * -1; - - const newZoomData = touchStartRef.current.zoomData.map((zoom) => { - const option = options[zoom.axisId]; - if (!option || !option.panning) { - return zoom; - } - - const min = zoom.start; - const max = zoom.end; - const span = max - min; - const MIN_PERCENT = option.minStart; - const MAX_PERCENT = option.maxEnd; - - const movement = option.axisDirection === 'x' ? movementX : movementY; - const dimension = option.axisDirection === 'x' ? drawingArea.width : drawingArea.height; - - let newMinPercent = min - (movement / dimension) * span; - let newMaxPercent = max - (movement / dimension) * span; - - if (newMinPercent < MIN_PERCENT) { - newMinPercent = MIN_PERCENT; - newMaxPercent = newMinPercent + span; - } - - if (newMaxPercent > MAX_PERCENT) { - newMaxPercent = MAX_PERCENT; - newMinPercent = newMaxPercent - span; - } - - if ( - newMinPercent < MIN_PERCENT || - newMaxPercent > MAX_PERCENT || - span < option.minSpan || - span > option.maxSpan - ) { - return zoom; - } - - return { - ...zoom, - start: newMinPercent, - end: newMaxPercent, - }; - }); - - setZoomData(newZoomData); - }; - - const handleDown = (event: PointerEvent) => { - eventCacheRef.current.push(event); - const point = getSVGPoint(element, event); - - if (!instance.isPointInside(point)) { - return; - } - - // If there is only one pointer, prevent selecting text - if (eventCacheRef.current.length === 1) { - event.preventDefault(); - } - - isDraggingRef.current = true; - setIsInteracting(true); - - touchStartRef.current = { - x: point.x, - y: point.y, - zoomData, - }; - }; - - const handleUp = (event: PointerEvent) => { - eventCacheRef.current.splice( - eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), - 1, - ); - setIsInteracting(false); - isDraggingRef.current = false; - touchStartRef.current = null; - }; - - element.addEventListener('pointerdown', handleDown); - document.addEventListener('pointermove', handlePan); - document.addEventListener('pointerup', handleUp); - document.addEventListener('pointercancel', handleUp); - document.addEventListener('pointerleave', handleUp); - - return () => { - element.removeEventListener('pointerdown', handleDown); - document.removeEventListener('pointermove', handlePan); - document.removeEventListener('pointerup', handleUp); - document.removeEventListener('pointercancel', handleUp); - document.removeEventListener('pointerleave', handleUp); - }; - }, [ - instance, - svgRef, - isDraggingRef, - setIsInteracting, - zoomData, - setZoomData, - isPanEnabled, - options, - drawingArea.width, - drawingArea.height, - ]); + // const store = useStore<[UseChartProCartesianAxisSignature]>(); + // const options = useSelector(store, selectorChartZoomOptions); + // const isPanEnabled = options.fo; + // const setZoomMap = React.useCallback( + // (updateFunction: (zoomMap: Map) => Map) => + // store.update((prev) => ({ + // ...prev, + // zoom: { + // ...prev.zoom, + // zoomMap: updateFunction(prev.zoom.zoomMap), + // }, + // })), + // [store], + // ); + // const setIsInteracting = React.useCallback( + // (newValue: boolean) => + // store.update((prev) => ({ + // ...prev, + // zoom: { + // ...prev.zoom, + // isInteracting: newValue, + // }, + // })), + // [store], + // ); + // const drawingArea = useDrawingArea(); + // const { instance } = useChartContext(); + // const svgRef = useSvgRef(); + // const isDraggingRef = React.useRef(false); + // const touchStartRef = React.useRef<{ x: number; y: number; zoomData: ZoomData[] } | null>(null); + // const eventCacheRef = React.useRef([]); + // React.useEffect(() => { + // const element = svgRef.current; + // if (element === null || !isPanEnabled) { + // return () => {}; + // } + // const handlePan = (event: PointerEvent) => { + // if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) { + // return; + // } + // if (touchStartRef.current == null) { + // return; + // } + // const point = getSVGPoint(element, event); + // const movementX = point.x - touchStartRef.current.x; + // const movementY = (point.y - touchStartRef.current.y) * -1; + // const newZoomData = touchStartRef.current.zoomData.map((zoom) => { + // const option = options[zoom.axisId]; + // if (!option || !option.panning) { + // return zoom; + // } + // const min = zoom.start; + // const max = zoom.end; + // const span = max - min; + // const MIN_PERCENT = option.minStart; + // const MAX_PERCENT = option.maxEnd; + // const movement = option.axisDirection === 'x' ? movementX : movementY; + // const dimension = option.axisDirection === 'x' ? drawingArea.width : drawingArea.height; + // let newMinPercent = min - (movement / dimension) * span; + // let newMaxPercent = max - (movement / dimension) * span; + // if (newMinPercent < MIN_PERCENT) { + // newMinPercent = MIN_PERCENT; + // newMaxPercent = newMinPercent + span; + // } + // if (newMaxPercent > MAX_PERCENT) { + // newMaxPercent = MAX_PERCENT; + // newMinPercent = newMaxPercent - span; + // } + // if ( + // newMinPercent < MIN_PERCENT || + // newMaxPercent > MAX_PERCENT || + // span < option.minSpan || + // span > option.maxSpan + // ) { + // return zoom; + // } + // return { + // ...zoom, + // start: newMinPercent, + // end: newMaxPercent, + // }; + // }); + // setZoomData(newZoomData); + // }; + // const handleDown = (event: PointerEvent) => { + // eventCacheRef.current.push(event); + // const point = getSVGPoint(element, event); + // if (!instance.isPointInside(point)) { + // return; + // } + // // If there is only one pointer, prevent selecting text + // if (eventCacheRef.current.length === 1) { + // event.preventDefault(); + // } + // isDraggingRef.current = true; + // setIsInteracting(true); + // touchStartRef.current = { + // x: point.x, + // y: point.y, + // zoomData, + // }; + // }; + // const handleUp = (event: PointerEvent) => { + // eventCacheRef.current.splice( + // eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), + // 1, + // ); + // setIsInteracting(false); + // isDraggingRef.current = false; + // touchStartRef.current = null; + // }; + // element.addEventListener('pointerdown', handleDown); + // document.addEventListener('pointermove', handlePan); + // document.addEventListener('pointerup', handleUp); + // document.addEventListener('pointercancel', handleUp); + // document.addEventListener('pointerleave', handleUp); + // return () => { + // element.removeEventListener('pointerdown', handleDown); + // document.removeEventListener('pointermove', handlePan); + // document.removeEventListener('pointerup', handleUp); + // document.removeEventListener('pointercancel', handleUp); + // document.removeEventListener('pointerleave', handleUp); + // }; + // }, [ + // instance, + // svgRef, + // isDraggingRef, + // setIsInteracting, + // zoomData, + // setZoomData, + // isPanEnabled, + // options, + // drawingArea.width, + // drawingArea.height, + // ]); }; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts index 70b53b847411..1371b02788ae 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts @@ -1,9 +1,18 @@ 'use client'; import * as React from 'react'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { getSVGPoint, useChartContext } from '@mui/x-charts/internals'; -import { useZoom } from './useZoom'; -import { DefaultizedZoomOptions, ZoomData } from './Zoom.types'; +import { + AxisId, + DefaultizedZoomOption, + getSVGPoint, + UseChartCartesianAxisSignature, + useChartContext, + useSelector, + useStore, + ZoomData, +} from '@mui/x-charts/internals'; +import { UseChartProZoomState } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; +import { selectorChartZoomOptions } from '../../internals/plugins/useChartProZoom'; /** * Helper to get the range (in percents of a reference range) corresponding to a given scale. @@ -15,7 +24,7 @@ const zoomAtPoint = ( centerRatio: number, scaleRatio: number, currentZoomData: ZoomData, - options: DefaultizedZoomOptions, + options: Record, ) => { const MIN_RANGE = options.minStart; const MAX_RANGE = options.maxEnd; @@ -56,7 +65,33 @@ const zoomAtPoint = ( }; export const useSetupZoom = () => { - const { setZoomData, isZoomEnabled, options, setIsInteracting } = useZoom(); + const store = useStore<[UseChartCartesianAxisSignature, UseChartProZoomState]>(); + + const options = useSelector(store, selectorChartZoomOptions); + const isZoomEnabled = Object.keys(options).length > 0; + const setZoomMap = React.useCallback( + (updateFunction: (zoomMap: Map) => Map) => + store.update((prev) => ({ + ...prev, + zoom: { + ...prev.zoom, + zoomMap: updateFunction(prev.zoom.zoomMap), + }, + })), + [store], + ); + const setIsInteracting = React.useCallback( + (newValue: boolean) => + store.update((prev) => ({ + ...prev, + zoom: { + ...prev.zoom, + isInteracting: newValue, + }, + })), + [store], + ); + const drawingArea = useDrawingArea(); const { instance } = useChartContext(); @@ -93,11 +128,14 @@ export const useSetupZoom = () => { setIsInteracting(false); }, 166); - setZoomData((prevZoomData) => { - return prevZoomData.map((zoom) => { + store.update((prevState) => { + const newZoomData = new Map(prevState.zoom.zoomMap); + + let updated = false; + newZoomData.forEach((zoom, key) => { const option = options[zoom.axisId]; if (!option) { - return zoom; + return; } const centerRatio = @@ -109,11 +147,23 @@ export const useSetupZoom = () => { const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { - return zoom; + return; } - return { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }; + updated = true; + + newZoomData.set(key, { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }); }); + + return updated + ? { + ...prevState, + zoom: { + ...prevState.zoom, + zoomMap: newZoomData, + }, + } + : prevState; }); }; @@ -140,11 +190,14 @@ export const useSetupZoom = () => { const firstEvent = eventCacheRef.current[0]; const curDiff = getDiff(eventCacheRef.current); - setZoomData((prevZoomData) => { - const newZoomData = prevZoomData.map((zoom) => { - const option = options[zoom.axisId]; + setZoomMap((prevZoomData) => { + const newZoomData = new Map(prevZoomData); + let updated = false; + + prevZoomData.forEach((zoom, key) => { + const option = options[key]; if (!option) { - return zoom; + return; } const { scaleRatio, isZoomIn } = getPinchScaleRatio( @@ -155,7 +208,7 @@ export const useSetupZoom = () => { // If the scale ratio is 0, it means the pinch gesture is not valid. if (scaleRatio === 0) { - return zoom; + return; } const point = getSVGPoint(element, firstEvent); @@ -168,12 +221,15 @@ export const useSetupZoom = () => { const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { - return zoom; + return; } - return { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }; + updated = true; + newZoomData.set(key, { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }); }); + eventPrevDiff.current = curDiff; - return newZoomData; + + return updated ? newZoomData : prevZoomData; }); } @@ -218,7 +274,7 @@ export const useSetupZoom = () => { clearTimeout(interactionTimeoutRef.current); } }; - }, [svgRef, setZoomData, drawingArea, isZoomEnabled, options, setIsInteracting, instance]); + }, [svgRef, drawingArea, isZoomEnabled, options, setIsInteracting, instance, setZoomMap, store]); }; /** diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts index 5e21d08de345..2ac4bac6fad5 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts @@ -1,24 +1,15 @@ 'use client'; -import * as React from 'react'; -import { ZoomContext } from './ZoomContext'; -import { ZoomState } from './Zoom.types'; +import { useSelector, useStore } from '@mui/x-charts/internals'; +import { selectorChartZoomIsInteracting } from '../../internals/plugins/useChartProZoom'; /** * Get access to the zoom state. * - * @returns {ZoomState} The zoom state. + * @returns {boolean} Inform the zoom is interacting. */ -export function useZoom(): ZoomState { - const { data, isInitialized } = React.useContext(ZoomContext); +export function useZoomIsInteracting(): boolean { + const store = useStore<[UseChartProCartesianAxisSignature]>(); + const isInteracting = useSelector(store, selectorChartZoomIsInteracting); - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the zoom context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - return data; + return isInteracting; } diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts deleted file mode 100644 index df07411bade8..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeAxis.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '@mui/x-charts/constants'; -import { AxisConfig, ChartsAxisProps, DatasetType, ScaleName } from '@mui/x-charts/internals'; -import { MakeOptional } from '@mui/x-internals/types'; - -export const defaultizeAxis = ( - inAxis: MakeOptional, 'id'>[] | undefined, - dataset: DatasetType | undefined, - axisName: 'x' | 'y', -) => { - const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY; - - return [ - ...(inAxis?.map((axis, index) => ({ id: `defaultized-${axisName}-axis-${index}`, ...axis })) ?? - []), - ...(inAxis === undefined || inAxis.findIndex(({ id }) => id === DEFAULT_AXIS_KEY) === -1 - ? [{ id: DEFAULT_AXIS_KEY, scaleType: 'linear' as const }] - : []), - ].map((axisConfig) => { - const dataKey = axisConfig.dataKey; - if (dataKey === undefined || axisConfig.data !== undefined) { - return axisConfig; - } - if (dataset === undefined) { - throw new Error(`MUI X: ${axisName}-axis uses \`dataKey\` but no \`dataset\` is provided.`); - } - return { - ...axisConfig, - data: dataset.map((d) => d[dataKey]), - }; - }); -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts deleted file mode 100644 index da0626d72178..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/getAxisExtremum.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { AxisConfig } from '../../../../models'; -import { CartesianChartSeriesType } from '../../../../models/seriesType/config'; -import { ChartSeriesConfig } from '../../models/seriesConfig'; -import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; -import { - CartesianExtremumGetter, - CartesianExtremumGetterResult, -} from '../../models/seriesConfig/extremumGetter.types'; -import { GetZoomAxisFilters } from './useChartProCartesianAxis.types'; - -const axisExtremumCallback = ( - acc: CartesianExtremumGetterResult, - chartType: TSeriesType, - axis: AxisConfig, - axisDirection: 'x' | 'y', - seriesConfig: ChartSeriesConfig, - axisIndex: number, - formattedSeries: ProcessedSeries, - getFilters?: GetZoomAxisFilters, -): CartesianExtremumGetterResult => { - const getter = - axisDirection === 'x' - ? seriesConfig[chartType].xExtremumGetter - : seriesConfig[chartType].yExtremumGetter; - const series = formattedSeries[chartType]?.series ?? {}; - - const [minChartTypeData, maxChartTypeData] = (getter as CartesianExtremumGetter)?.({ - series, - axis, - axisIndex, - isDefaultAxis: axisIndex === 0, - getFilters, - }) ?? [Infinity, -Infinity]; - - const [minData, maxData] = acc; - - return [Math.min(minChartTypeData, minData), Math.max(maxChartTypeData, maxData)]; -}; - -export const getAxisExtremum = ( - axis: AxisConfig, - axisDirection: 'x' | 'y', - seriesConfig: ChartSeriesConfig, - axisIndex: number, - formattedSeries: ProcessedSeries, - getFilters?: GetZoomAxisFilters, -) => { - const charTypes = Object.keys(seriesConfig) as CartesianChartSeriesType[]; - - const extremums = charTypes.reduce( - (acc, charType) => - axisExtremumCallback( - acc, - charType, - axis, - axisDirection, - seriesConfig, - axisIndex, - formattedSeries, - getFilters, - ), - [Infinity, -Infinity], - ); - - if (Number.isNaN(extremums[0]) || Number.isNaN(extremums[1])) { - return [Infinity, -Infinity]; - } - - return extremums; -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts deleted file mode 100644 index 98382f151e6a..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { useChartCartesianAxis } from './useChartProCartesianAxis'; -export type { - UseChartCartesianAxisSignature, - UseChartCartesianAxisParameters, - UseChartCartesianAxisDefaultizedParameters, -} from './useChartProCartesianAxis.types'; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts deleted file mode 100644 index 3248e643f4fb..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChartRootSelector, createSelector } from '../../utils/selectors'; -import { UseChartCartesianAxisSignature } from './useChartProCartesianAxis.types'; - -export const selectorChartCartesianAxisState: ChartRootSelector = ( - state, -) => state.cartesianAxis; - -export const selectorChartXAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.x); - -export const selectorChartYAxis = createSelector(selectorChartCartesianAxisState, (axis) => axis.y); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts deleted file mode 100644 index 61b534c05da2..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.ts +++ /dev/null @@ -1,120 +0,0 @@ -'use client'; -import * as React from 'react'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; -import { - computeAxisValue, - selectorChartDrawingArea, - selectorChartSeriesState, - ChartPlugin, - useSelector, - defaultizeAxis, - AxisId, -} from '@mui/x-charts/internals'; -import { blueberryTwilightPalette } from '@mui/x-charts/colorPalettes'; -import { - DefaultizedZoomOptions, - UseChartProCartesianAxisSignature, - ZoomData, -} from './useChartProCartesianAxis.types'; -import { defaultizeZoom } from './defaultizeZoom'; -import { createZoomMap } from './useChartProCartesianAxis.utils'; - -export const useChartProCartesianAxis: ChartPlugin = ({ - params, - store, - models, -}) => { - useEnhancedEffect(() => { - store.update((prevState) => ({ - ...prevState, - zoom: { - ...prevState.zoom, - zoomMap: createZoomMap(models.zoom.value), - }, - })); - }, [store, models.zoom.value]); - - const { xAxis, yAxis, dataset } = params; - - // The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartProCartesianAxis` - // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one - const isFirstRender = React.useRef(true); - React.useEffect(() => { - if (isFirstRender.current) { - isFirstRender.current = false; - return; - } - - const defaultizedXAxis = defaultizeAxis(xAxis, dataset, 'x'); - const defaultizedYAxis = defaultizeAxis(yAxis, dataset, 'y'); - store.update((prev) => { - return { - ...prev, - cartesianAxis: { - x: defaultizedXAxis, - y: defaultizedYAxis, - }, - }; - }); - }, [xAxis, yAxis, dataset, store]); - - return {}; -}; - -useChartProCartesianAxis.params = { - xAxis: true, - yAxis: true, - dataset: true, - zoom: true, - onZoomChange: true, -}; - -useChartProCartesianAxis.getDefaultizedParams = ({ params }) => ({ - ...params, - colors: params.colors ?? blueberryTwilightPalette, - theme: params.theme ?? 'light', -}); - -const DEFAULT_ZOOMS: ZoomData[] = []; - -useChartProCartesianAxis.models = { - zoom: { - getDefaultValue: () => DEFAULT_ZOOMS, - }, -}; - -useChartProCartesianAxis.getInitialState = (params) => { - const defaultizedXAxis = defaultizeAxis(params.xAxis, params.dataset, 'x'); - const defaultizedYAxis = defaultizeAxis(params.yAxis, params.dataset, 'y'); - - const options = { - ...defaultizedXAxis.reduce>((acc, v) => { - const { zoom, id: axisId } = v; - const defaultizedZoom = defaultizeZoom(zoom, axisId, 'x'); - if (defaultizedZoom) { - acc[axisId] = defaultizedZoom; - } - return acc; - }, {}), - ...defaultizedYAxis.reduce>((acc, v) => { - const { zoom, id: axisId } = v; - const defaultizedZoom = defaultizeZoom(zoom, axisId, 'y'); - if (defaultizedZoom) { - acc[axisId] = defaultizedZoom; - } - return acc; - }, {}), - }; - - return { - zoom: { - options, - zoomMap: createZoomMap(params.zoom === undefined ? [] : params.zoom), - isInteracting: false, - }, - cartesianAxis: { - x: defaultizedXAxis, - y: defaultizedYAxis, - }, - }; -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts deleted file mode 100644 index 8b11b42796d8..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { MakeOptional } from '@mui/x-internals/types'; -import { - AxisDefaultized, - ScaleName, - ChartsXAxisProps, - ChartsYAxisProps, - AxisId, - AxisConfig, - UseChartSeriesSignature, - DatasetType, - ChartPluginSignature, -} from '@mui/x-charts/internals'; - -export type DefaultizedAxisConfig = { - [axisId: AxisId]: AxisDefaultized; -}; - -export interface UseChartProCartesianAxisParameters { - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis?: MakeOptional, 'id'>[]; - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis?: MakeOptional, 'id'>[]; - dataset?: DatasetType; - /** - * The list of zoom data related to each axis. - */ - zoom?: ZoomData[]; - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange?: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void; -} - -export type UseChartProCartesianAxisDefaultizedParameters = UseChartProCartesianAxisParameters & {}; - -export type ZoomOptions = { - /** - * The starting percentage of the zoom range. In the range of 0 to 100. - * - * @default 0 - */ - minStart?: number; - /** - * The ending percentage of the zoom range. In the range of 0 to 100. - * - * @default 100 - */ - maxEnd?: number; - /** - * The step size of the zooming function. Defines the granularity of the zoom. - * - * @default 5 - */ - step?: number; - /** - * Restricts the minimum span size in the range of 0 to 100. - * - * If the span size is smaller than the minSpan, the span will be resized to the minSpan. - * - * @default 10 - */ - minSpan?: number; - /** - * Restricts the maximum span size in the range of 0 to 100. - * - * If the span size is larger than the maxSpan, the span will be resized to the maxSpan. - * - * @default 100 - */ - maxSpan?: number; - /** - * Set to `false` to disable panning. Useful when you want to pan programmatically, - * or to show only a specific section of the chart. - * - * @default true - */ - panning?: boolean; - /** - * Defines how to filter the axis data when it is outside of the zoomed range of this axis. - * - * - `keep`: The data outside the zoomed range is kept. And the other axes will stay the same. - * - `discard`: The data outside the zoomed range is discarded for the other axes. - * The other axes will be adjusted to fit the zoomed range. - * - * @default 'keep' - */ - filterMode?: 'discard' | 'keep'; -}; - -export type DefaultizedZoomOptions = Required & { - axisId: AxisId; - axisDirection: 'x' | 'y'; -}; - -export interface UseChartProCartesianAxisState { - zoom: { - /** - * The zoom options for each axis. - */ - options: Record; - /** - * Whether the user is currently interacting with the chart. - * This is useful to prevent animations from running while the user is interacting. - */ - isInteracting: boolean; - /** - * Mapping of axis id to the zoom data. - */ - zoomMap: Map; - }; - cartesianAxis: { - x: DefaultizedAxisConfig; - y: DefaultizedAxisConfig; - }; -} - -export type ExtremumFilter = ( - value: { x: number | Date | string | null; y: number | Date | string | null }, - dataIndex: number, -) => boolean; - -export interface UseChartProCartesianAxisInstance {} - -export type UseChartProCartesianAxisSignature = ChartPluginSignature<{ - params: UseChartProCartesianAxisParameters; - defaultizedParams: UseChartProCartesianAxisDefaultizedParameters; - state: UseChartProCartesianAxisState; - // instance: UseChartProCartesianAxisInstance; - modelNames: 'zoom'; - dependencies: [UseChartSeriesSignature]; -}>; - -export type ZoomData = { axisId: AxisId; start: number; end: number }; - -export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; - -export type ZoomAxisFilters = Record; - -export type GetZoomAxisFilters = (params: { - currentAxisId: AxisId | undefined; - seriesXAxisId?: AxisId; - seriesYAxisId?: AxisId; - isDefaultAxis: boolean; -}) => ExtremumFilter; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts deleted file mode 100644 index 57ce8e20a4c8..000000000000 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/zoom.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Applies the zoom into the scale range. - * It changes the screen coordinates that the scale covers. - * Not the data that is displayed. - * - * @param scaleRange the original range in real screen coordinates. - * @param zoomRange the zoom range in percentage. - * @returns zoomed range in real screen coordinates. - */ -export const zoomScaleRange = ( - scaleRange: [number, number] | number[], - zoomRange: [number, number] | number[], -) => { - const rangeGap = scaleRange[1] - scaleRange[0]; - const zoomGap = zoomRange[1] - zoomRange[0]; - - // If current zoom show the scale between p1 and p2 percents - // The range should be extended by adding [0, p1] and [p2, 100] segments - const min = scaleRange[0] - (zoomRange[0] * rangeGap) / zoomGap; - const max = scaleRange[1] + ((100 - zoomRange[1]) * rangeGap) / zoomGap; - - return [min, max]; -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/defaultizeZoom.ts similarity index 61% rename from packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts rename to packages/x-charts-pro/src/internals/plugins/useChartProZoom/defaultizeZoom.ts index 811af3ff2e90..4c0a076f98c7 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/defaultizeZoom.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/defaultizeZoom.ts @@ -1,7 +1,6 @@ -import { AxisId } from '@mui/x-charts/internals'; -import { DefaultizedZoomOptions, ZoomOptions } from './useChartProCartesianAxis.types'; +import { AxisId, DefaultizedZoomOption, ZoomOption } from '@mui/x-charts/internals'; -const defaultZoomOptions: Required = { +const defaultZoomOptions: Required = { minStart: 0, maxEnd: 100, step: 5, @@ -12,10 +11,10 @@ const defaultZoomOptions: Required = { }; export const defaultizeZoom = ( - zoom: boolean | ZoomOptions | undefined, + zoom: boolean | ZoomOption | undefined, axisId: AxisId, axisDirection: 'x' | 'y', -): DefaultizedZoomOptions | undefined => { +): DefaultizedZoomOption | undefined => { if (!zoom) { return undefined; } diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/index.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/index.ts new file mode 100644 index 000000000000..48ce05ccb528 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/index.ts @@ -0,0 +1,2 @@ +export * from './useChartProZoom.selectors'; +export * from './useChartProZoom'; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts new file mode 100644 index 000000000000..8015beb684b4 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts @@ -0,0 +1,15 @@ +import { ChartRootSelector, createSelector } from '@mui/x-charts/internals'; +import { UseChartProZoomSignature } from './useChartProZoom.types'; + +export const selectorChartZoomState: ChartRootSelector = (state) => + state.zoom; + +export const selectorChartZoomOptions = createSelector( + selectorChartZoomState, + (zoom) => zoom.options, +); + +export const selectorChartZoomIsInteracting = createSelector( + selectorChartZoomState, + (zoom) => zoom.isInteracting, +); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts new file mode 100644 index 000000000000..e2aa79b7f095 --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts @@ -0,0 +1,70 @@ +'use client'; +import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; +import { ChartPlugin, AxisId, DefaultizedZoomOption } from '@mui/x-charts/internals'; +import { UseChartProZoomSignature } from './useChartProZoom.types'; +import { defaultizeZoom } from './defaultizeZoom'; +import { createZoomMap } from './useChartProZoom.utils'; +import { initializeZoomData } from '../../../context/ZoomProvider/initializeZoomData'; + +export const useChartProZoom: ChartPlugin = ({ store, models }) => { + useEnhancedEffect(() => { + store.update((prevState) => ({ + ...prevState, + zoom: { + ...prevState.zoom, + zoomMap: createZoomMap(models.zoom.value), + }, + })); + }, [store, models.zoom.value]); + + return {}; +}; + +useChartProZoom.params = { + zoom: true, + onZoomChange: true, +}; + +useChartProZoom.getDefaultizedParams = ({ params }) => { + const options = { + ...params.defaultizedXAxis.reduce>((acc, v) => { + const { zoom, id: axisId } = v; + const defaultizedZoom = defaultizeZoom(zoom, axisId, 'x'); + if (defaultizedZoom) { + acc[axisId] = defaultizedZoom; + } + return acc; + }, {}), + ...params.defaultizedYAxis.reduce>((acc, v) => { + const { zoom, id: axisId } = v; + const defaultizedZoom = defaultizeZoom(zoom, axisId, 'y'); + if (defaultizedZoom) { + acc[axisId] = defaultizedZoom; + } + return acc; + }, {}), + }; + + return { + ...params, + options, + }; +}; + +useChartProZoom.models = { + zoom: { + getDefaultValue: (params) => initializeZoomData(params.options), + }, +}; + +useChartProZoom.getInitialState = (params) => { + return { + zoom: { + options: params.options, + zoomMap: createZoomMap( + params.zoom === undefined ? initializeZoomData(params.options) : params.zoom, + ), + isInteracting: false, + }, + }; +}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts new file mode 100644 index 000000000000..6cd3c2e69bbe --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts @@ -0,0 +1,59 @@ +import { + AxisId, + UseChartSeriesSignature, + ChartPluginSignature, + DefaultizedZoomOption, + UseChartCartesianAxisSignature, + UseChartCartesianAxisDefaultizedParameters, + ZoomData, +} from '@mui/x-charts/internals'; + +export interface UseChartProZoomParameters { + /** + * The list of zoom data related to each axis. + */ + zoom?: ZoomData[]; + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange?: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void; +} + +export type UseChartProZoomDefaultizedParameters = UseChartProZoomParameters & + UseChartCartesianAxisDefaultizedParameters & { + /** + * The zoom options for each axis. + */ + options: Record; + }; + +export interface UseChartProZoomState { + zoom: { + /** + * The zoom options for each axis. + */ + options: Record; + /** + * Whether the user is currently interacting with the chart. + * This is useful to prevent animations from running while the user is interacting. + */ + isInteracting: boolean; + /** + * Mapping of axis id to the zoom data. + */ + zoomMap: Map; + }; +} + +export interface UseChartProZoomInstance {} + +export type UseChartProZoomSignature = ChartPluginSignature<{ + params: UseChartProZoomParameters; + defaultizedParams: UseChartProZoomDefaultizedParameters; + state: UseChartProZoomState; + instance: UseChartProZoomInstance; + modelNames: 'zoom'; + dependencies: [UseChartSeriesSignature, UseChartCartesianAxisSignature]; +}>; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts similarity index 67% rename from packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts rename to packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts index 304813ccff66..869c37d8e5f8 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.utils.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts @@ -1,5 +1,4 @@ -import { AxisId } from '@mui/x-charts/internals'; -import { ZoomData } from './useChartProCartesianAxis.types'; +import { AxisId, ZoomData } from '@mui/x-charts/internals'; export const createZoomMap = (zoom: ZoomData[]) => { const selectedItemsMap = new Map(); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/zoom.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/zoom.types.ts new file mode 100644 index 000000000000..e56f1677eeee --- /dev/null +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/zoom.types.ts @@ -0,0 +1,53 @@ +export interface ZoomOption { + /** + * The starting percentage of the zoom range. In the range of 0 to 100. + * + * @default 0 + */ + minStart?: number; + /** + * The ending percentage of the zoom range. In the range of 0 to 100. + * + * @default 100 + */ + maxEnd?: number; + /** + * The step size of the zooming function. Defines the granularity of the zoom. + * + * @default 5 + */ + step?: number; + /** + * Restricts the minimum span size in the range of 0 to 100. + * + * If the span size is smaller than the minSpan, the span will be resized to the minSpan. + * + * @default 10 + */ + minSpan?: number; + /** + * Restricts the maximum span size in the range of 0 to 100. + * + * If the span size is larger than the maxSpan, the span will be resized to the maxSpan. + * + * @default 100 + */ + maxSpan?: number; + /** + * Set to `false` to disable panning. Useful when you want to pan programmatically, + * or to show only a specific section of the chart. + * + * @default true + */ + panning?: boolean; + /** + * Defines how to filter the axis data when it is outside of the zoomed range of this axis. + * + * - `keep`: The data outside the zoomed range is kept. And the other axes will stay the same. + * - `discard`: The data outside the zoomed range is discarded for the other axes. + * The other axes will be adjusted to fit the zoomed range. + * + * @default 'keep' + */ + filterMode?: 'discard' | 'keep'; +} diff --git a/packages/x-charts-pro/src/typeOverloads/modules.ts b/packages/x-charts-pro/src/typeOverloads/modules.ts index 734e3e911b7e..b92ab1b87618 100644 --- a/packages/x-charts-pro/src/typeOverloads/modules.ts +++ b/packages/x-charts-pro/src/typeOverloads/modules.ts @@ -1,11 +1,12 @@ import { DefaultizedProps } from '@mui/x-internals/types'; +import { AxisId } from '@mui/x-charts/internals'; import { HeatmapItemIdentifier, HeatmapSeriesType, DefaultizedHeatmapSeriesType, HeatmapValueType, } from '../models/seriesType/heatmap'; -import { ZoomOptions } from '../context/ZoomProvider'; +import { ZoomOption as ZoomOptionPro } from '../internals/plugins/useChartProZoom/zoom.types'; declare module '@mui/x-charts/internals' { interface ChartsSeriesConfig { @@ -19,7 +20,14 @@ declare module '@mui/x-charts/internals' { }; } + interface ZoomOption extends ZoomOptionPro {} + + interface DefaultizedZoomOption extends Required { + axisId: AxisId; + axisDirection: 'x' | 'y'; + } + interface AxisConfigExtension { - zoom?: boolean | ZoomOptions; + zoom?: boolean | ZoomOption; } } diff --git a/packages/x-charts-pro/tsconfig.json b/packages/x-charts-pro/tsconfig.json index 5f862d31ec2b..7c877b814868 100644 --- a/packages/x-charts-pro/tsconfig.json +++ b/packages/x-charts-pro/tsconfig.json @@ -10,5 +10,5 @@ ], "noImplicitAny": false }, - "include": ["src/**/*", "../../test/utils/addChaiAssertions.ts"] + "include": ["src/**/*", "../../test/utils/addChaiAssertions.ts", "../x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts"] } diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index 6efb810464a3..dfd45ebc8082 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -17,6 +17,7 @@ export * from './plugins/corePlugins/useChartSeries'; export * from './plugins/corePlugins/useChartDimensions'; export * from './plugins/featurePlugins/useChartCartesianAxis'; export * from './plugins/featurePlugins/useChartInteraction'; +export * from './plugins/utils/selectors'; export * from './store/useCharts'; export * from './store/useStore'; @@ -30,7 +31,6 @@ export * from './getSVGPoint'; export * from './isDefined'; export { unstable_cleanupDOM } from './domUtils'; export * from './getScale'; -export * from './plugins/featurePlugins/useChartCartesianAxis/computeAxisValue'; // contexts diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts index 3c31d3697da6..3bbbfba2164e 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts @@ -3,5 +3,6 @@ export type { UseChartSeriesSignature, UseChartSeriesParameters, UseChartSeriesDefaultizedParameters, + ProcessedSeries } from './useChartSeries.types'; export * from './useChartSeries.selectors'; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts index 28bbc1e7417a..a6f6cd9c489d 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts @@ -6,6 +6,7 @@ import { ChartsYAxisProps, isBandScaleConfig, isPointScaleConfig, + AxisId, } from '../../../../models/axis'; import { CartesianChartSeriesType, ChartSeriesType } from '../../../../models/seriesType/config'; import { getColorScale, getOrdinalColorScale } from '../../../colorScale'; @@ -15,40 +16,15 @@ import { zoomScaleRange } from './zoom'; import { getAxisExtremum } from './getAxisExtremum'; import type { ChartDrawingArea } from '../../../../hooks'; import { ChartSeriesConfig } from '../../models/seriesConfig'; -import { - DefaultizedAxisConfig, - GetZoomAxisFilters, - ZoomData, - ZoomOptions, -} from './useChartCartesianAxis.types'; +import { DefaultizedAxisConfig, DefaultizedZoomOption } from './useChartCartesianAxis.types'; import { ProcessedSeries } from '../../corePlugins/useChartSeries/useChartSeries.types'; +import { GetZoomAxisFilters, ZoomData } from './zoom.types'; function getRange( drawingArea: ChartDrawingArea, axisDirection: 'x' | 'y', // | 'rotation' | 'radius', - axis: AxisConfig< - ScaleName, - any, - // ChartsRotationAxisProps | ChartsRotationAxisProps | - ChartsAxisProps - >, + axis: AxisConfig, ): [number, number] { - // if (axisDirection === 'rotation') { - // const { startAngle = 0, endAngle = startAngle + 360 } = axis as AxisConfig< - // ScaleName, - // any, - // ChartsRotationAxisProps - // >; - // return axis.reverse - // ? [(Math.PI * startAngle) / 180, (Math.PI * endAngle) / 180] - // : [(Math.PI * endAngle) / 180, (Math.PI * startAngle) / 180]; - // } - // if (axisDirection === 'radius') { - // const { minRadius = 0, maxRadius = Math.min(drawingArea.width, drawingArea.height) / 2 } = - // axis as AxisConfig; - // return [minRadius, maxRadius]; - // } - const range: [number, number] = axisDirection === 'x' ? [drawingArea.left, drawingArea.left + drawingArea.width] @@ -81,8 +57,8 @@ type ComputeCommonParams = { drawingArea: ChartDrawingArea; formattedSeries: ProcessedSeries; seriesConfig: ChartSeriesConfig; - zoomData?: ZoomData[]; - zoomOptions?: ZoomOptions; + zoomMap?: Map; + zoomOptions?: Record; getFilters?: GetZoomAxisFilters; }; @@ -104,7 +80,7 @@ export function computeAxisValue({ axis: allAxis, seriesConfig, axisDirection, - zoomData, + zoomMap, zoomOptions, getFilters, }: ComputeCommonParams & { @@ -115,7 +91,7 @@ export function computeAxisValue({ allAxis.forEach((eachAxis, axisIndex) => { const axis = eachAxis as Readonly>>; const zoomOption = zoomOptions?.[axis.id]; - const zoom = zoomData?.find(({ axisId }) => axisId === axis.id); + const zoom = zoomMap?.get(axis.id); const zoomRange: [number, number] = zoom ? [zoom.start, zoom.end] : [0, 100]; const range = getRange(drawingArea, axisDirection, axis); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts similarity index 64% rename from packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts rename to packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts index 3d2518bf6b61..77aa7a0ee3af 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProCartesianAxis/createAxisFilterMapper.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts @@ -1,23 +1,42 @@ -import { getAxisExtremum, isDefined, getScale } from '@mui/x-charts/internals'; -import { ScaleName, AxisConfig } from '@mui/x-charts/models'; -import { ChartsAxisProps } from '@mui/x-charts/ChartsAxis'; -import { ZoomData } from '../../../context/ZoomProvider'; +import type { ChartsAxisProps } from '../../../../ChartsAxis'; +import { isDefined } from '../../../isDefined'; +import { AxisId } from '../../../../models/axis'; +import { CartesianChartSeriesType } from '../../../../models/seriesType/config'; +import { ProcessedSeries } from '../../corePlugins/useChartSeries'; +import { AxisConfig, ScaleName } from '../../../../models'; +import { ChartSeriesConfig } from '../../models/seriesConfig'; +import { getAxisExtremum } from './getAxisExtremum'; +import { + DefaultizedZoomOption, + ExtremumFilter, + GetZoomAxisFilters, + ZoomAxisFilters, + ZoomData, +} from './useChartCartesianAxis.types'; type CreateAxisFilterMapperParams = { - zoomData: ZoomData[]; - extremumGetter: ExtremumGettersConfig; - formattedSeries: FormattedSeries; + zoomMap: Map; + zoomOptions: Record; + seriesConfig: ChartSeriesConfig; + formattedSeries: ProcessedSeries; direction: 'x' | 'y'; }; export const createAxisFilterMapper = - ({ zoomData, extremumGetter, formattedSeries, direction }: CreateAxisFilterMapperParams) => + ({ + zoomMap, + zoomOptions, + seriesConfig, + formattedSeries, + direction, + }: CreateAxisFilterMapperParams) => (axis: AxisConfig, axisIndex: number): ExtremumFilter | null => { - if (typeof axis.zoom !== 'object' || axis.zoom.filterMode !== 'discard') { + const zoomOption = zoomOptions[axis.id]; + if (!zoomOption || zoomOption.filterMode !== 'discard') { return null; } - const zoom = zoomData?.find(({ axisId }) => axisId === axis.id); + const zoom = zoomMap?.get(axis.id); if (zoom === undefined || (zoom.start <= 0 && zoom.end >= 100)) { // No zoom, or zoom with all data visible @@ -30,7 +49,7 @@ export const createAxisFilterMapper = if (scaleType === 'point' || scaleType === 'band') { extremums = [0, (axis.data?.length ?? 1) - 1]; } else { - extremums = getAxisExtremum(axis, extremumGetter, axisIndex, formattedSeries); + extremums = getAxisExtremum(axis, direction, seriesConfig, axisIndex, formattedSeries); } let min: number | Date; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts index db358f39ba44..d54ceafc4c77 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/index.ts @@ -1,7 +1,5 @@ export { useChartCartesianAxis } from './useChartCartesianAxis'; -export type { - UseChartCartesianAxisSignature, - UseChartCartesianAxisParameters, - UseChartCartesianAxisDefaultizedParameters, -} from './useChartCartesianAxis.types'; +export type * from './useChartCartesianAxis.types'; export { defaultizeAxis } from './defaultizeAxis'; +export * from './computeAxisValue'; +export * from './zoom.types'; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts index 3c5ead144cef..6981209d2c27 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts @@ -3,55 +3,153 @@ import { selectorChartSeriesConfig, selectorChartSeriesProcessed, } from '../../corePlugins/useChartSeries'; -import { ChartSeriesType } from '../../../../models/seriesType/config'; -import { ChartRootSelector, createSelector } from '../../utils/selectors'; +import { createSelector } from '../../utils/selectors'; import { computeAxisValue } from './computeAxisValue'; import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; +import { ChartState } from '../../models/chart'; +import { createAxisFilterMapper, createGetAxisFilters } from './createAxisFilterMapper'; +import { ZoomAxisFilters } from './zoom.types'; -export const selectorChartCartesianAxisState: ChartRootSelector< - UseChartCartesianAxisSignature -> = (state) => state.cartesianAxis; +export const selectorChartCartesianAxisState = ( + state: ChartState<[UseChartCartesianAxisSignature]>, +) => state.cartesianAxis; + +const selectorChartZoomState = (state: ChartState<[UseChartCartesianAxisSignature]>) => state.zoom; export const selectorChartRawXAxis = createSelector( selectorChartCartesianAxisState, (axis) => axis.x, ); +export const selectorChartRawYAxis = createSelector( + selectorChartCartesianAxisState, + (axis) => axis.y, +); + +/** + * Following selectors are not exported because they exist in the MIT chart only to ba able to reuse the Zoom state from the pro. + */ + +const selectorChartZoomMap = createSelector(selectorChartZoomState, (zoom) => zoom?.zoomMap); + +const selectorChartZoomOptions = createSelector(selectorChartZoomState, (zoom) => zoom?.options); + +const selectorChartXFilter = createSelector( + [ + selectorChartZoomMap, + selectorChartZoomOptions, + selectorChartSeriesConfig, + selectorChartSeriesProcessed, + ], + (zoomMap, zoomOptions, seriesConfig, formattedSeries) => + zoomMap && + zoomOptions && + createAxisFilterMapper({ + zoomMap, + zoomOptions, + seriesConfig, + formattedSeries, + direction: 'x', + }), +); + +const selectorChartYFilter = createSelector( + [ + selectorChartZoomMap, + selectorChartZoomOptions, + selectorChartSeriesConfig, + selectorChartSeriesProcessed, + ], + (zoomMap, zoomOptions, seriesConfig, formattedSeries) => + zoomMap && + zoomOptions && + createAxisFilterMapper({ + zoomMap, + zoomOptions, + seriesConfig, + formattedSeries, + direction: 'y', + }), +); + +const selectorChartZoomAxisFilters = createSelector( + [selectorChartXFilter, selectorChartYFilter, selectorChartRawXAxis, selectorChartRawYAxis], + (xMapper, yMapper, xAxis, yAxis) => { + if (xMapper === undefined || yMapper === undefined) { + // Early return if there is no zoom. + return undefined; + } + + const xFilters = xAxis.reduce((acc, axis, index) => { + const filter = xMapper(axis, index); + if (filter !== null) { + acc[axis.id] = filter; + } + return acc; + }, {}); + + const yFilters = yAxis.reduce((acc, axis, index) => { + const filter = yMapper(axis, index); + if (filter !== null) { + acc[axis.id] = filter; + } + return acc; + }, {} as ZoomAxisFilters); + + if (Object.keys(xFilters).length === 0 && Object.keys(yFilters).length === 0) { + return undefined; + } + + return createGetAxisFilters({ ...xFilters, ...yFilters }); + }, +); + +/** + * The only interesting selectors that merge axis data and zoom if provided. + */ + export const selectorChartXAxis = createSelector( [ selectorChartRawXAxis, selectorChartDrawingArea, selectorChartSeriesProcessed, selectorChartSeriesConfig, + selectorChartZoomMap, + selectorChartZoomOptions, + selectorChartZoomAxisFilters, ], - (axis, drawingArea, formattedSeries, seriesConfig) => + (axis, drawingArea, formattedSeries, seriesConfig, zoomMap, zoomOptions, getFilters) => computeAxisValue({ drawingArea, formattedSeries, axis, seriesConfig, axisDirection: 'x', + zoomMap, + zoomOptions, + getFilters, }), ); -export const selectorChartRawYAxis = createSelector( - selectorChartCartesianAxisState, - (axis) => axis.y, -); - export const selectorChartYAxis = createSelector( [ selectorChartRawYAxis, selectorChartDrawingArea, selectorChartSeriesProcessed, selectorChartSeriesConfig, + selectorChartZoomMap, + selectorChartZoomOptions, + selectorChartZoomAxisFilters, ], - (axis, drawingArea, formattedSeries, seriesConfig) => + (axis, drawingArea, formattedSeries, seriesConfig, zoomMap, zoomOptions, getFilters) => computeAxisValue({ drawingArea, formattedSeries, axis, seriesConfig, axisDirection: 'y', + zoomMap, + zoomOptions, + getFilters, }), ); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts index b0419785101d..0e6616264445 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts @@ -45,15 +45,19 @@ useChartCartesianAxis.params = { dataset: true, }; -useChartCartesianAxis.getDefaultizedParams = ({ params }) => ({ - ...params, - colors: params.colors ?? blueberryTwilightPalette, - theme: params.theme ?? 'light', -}); +useChartCartesianAxis.getDefaultizedParams = ({ params }) => { + return { + ...params, + colors: params.colors ?? blueberryTwilightPalette, + theme: params.theme ?? 'light', + defaultizedXAxis: defaultizeAxis(params.xAxis, params.dataset, 'x'), + defaultizedYAxis: defaultizeAxis(params.yAxis, params.dataset, 'y'), + }; +}; -useChartCartesianAxis.getInitialState = ({ xAxis, yAxis, dataset }) => ({ +useChartCartesianAxis.getInitialState = (params) => ({ cartesianAxis: { - x: defaultizeAxis(xAxis, dataset, 'x'), - y: defaultizeAxis(yAxis, dataset, 'y'), + x: params.defaultizedXAxis, + y: params.defaultizedYAxis, }, }); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts index 275c9b3456cd..3a4c8abcc1e8 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts @@ -10,6 +10,7 @@ import { AxisConfig, } from '../../../../models/axis'; import { UseChartSeriesSignature } from '../../corePlugins/useChartSeries'; +import { ZoomData, ZoomOption } from './zoom.types'; export type DefaultizedAxisConfig = { [axisId: AxisId]: AxisDefaultized; @@ -34,20 +35,6 @@ export type CartesianContextState = { yAxisIds: AxisId[]; }; -// export type ZoomData = { axisId: AxisId; start: number; end: number }; - -// export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; -// export type ZoomOptions = Record; - -// export type ZoomAxisFilters = Record; - -// export type GetZoomAxisFilters = (params: { -// currentAxisId: AxisId | undefined; -// seriesXAxisId?: AxisId; -// seriesYAxisId?: AxisId; -// isDefaultAxis: boolean; -// }) => ExtremumFilter; - export interface UseChartCartesianAxisParameters { /** * The configuration of the x-axes. @@ -64,9 +51,32 @@ export interface UseChartCartesianAxisParameters { dataset?: DatasetType; } -export type UseChartCartesianAxisDefaultizedParameters = UseChartCartesianAxisParameters & {}; +export type UseChartCartesianAxisDefaultizedParameters = UseChartCartesianAxisParameters & { + defaultizedXAxis: AxisConfig[]; + defaultizedYAxis: AxisConfig[]; +}; + +export interface DefaultizedZoomOption extends Required { + axisId: AxisId; + axisDirection: 'x' | 'y'; +} export interface UseChartCartesianAxisState { + zoom?: { + /** + * The zoom options for each axis. + */ + options: Record; + /** + * Whether the user is currently interacting with the chart. + * This is useful to prevent animations from running while the user is interacting. + */ + isInteracting: boolean; + /** + * Mapping of axis id to the zoom data. + */ + zoomMap: Map; + }; cartesianAxis: { x: AxisConfig[]; y: AxisConfig[]; @@ -88,17 +98,3 @@ export type UseChartCartesianAxisSignature]; }>; - -export type ZoomData = { axisId: AxisId; start: number; end: number }; - -export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; -export type ZoomOptions = Record; - -export type ZoomAxisFilters = Record; - -export type GetZoomAxisFilters = (params: { - currentAxisId: AxisId | undefined; - seriesXAxisId?: AxisId; - seriesYAxisId?: AxisId; - isDefaultAxis: boolean; -}) => ExtremumFilter; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts new file mode 100644 index 000000000000..d67db2194e7e --- /dev/null +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts @@ -0,0 +1,19 @@ +// This file is here only to fix typing. The full typing of zoom states is defined in the pro library. +import { AxisId } from '../../../../models/axis'; +import type { ExtremumFilter } from './useChartCartesianAxis.types'; + +export type ZoomData = { axisId: AxisId; start: number; end: number }; + +export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; +export interface ZoomOption { + filterMode: ZoomFilterMode; +} + +export type ZoomAxisFilters = Record; + +export type GetZoomAxisFilters = (params: { + currentAxisId: AxisId | undefined; + seriesXAxisId?: AxisId; + seriesYAxisId?: AxisId; + isDefaultAxis: boolean; +}) => ExtremumFilter; diff --git a/packages/x-charts/src/internals/plugins/models/plugin.ts b/packages/x-charts/src/internals/plugins/models/plugin.ts index 94734314f2e1..caf391396c24 100644 --- a/packages/x-charts/src/internals/plugins/models/plugin.ts +++ b/packages/x-charts/src/internals/plugins/models/plugin.ts @@ -81,7 +81,10 @@ type PluginPropertyWithDependencies< MergeSignaturesProperty, TProperty> & Partial>; -export type ChartUsedParams = +export type ChartUsedParams = MergeSignaturesProperty< + TSignature['dependencies'], + 'defaultizedParams' +> & PluginPropertyWithDependencies; type ChartUsedDefaultizedParams = From f6ca0c0f532a714e9b114e4a133489cc79e60efe Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 09:52:15 +0100 Subject: [PATCH 12/32] scripts --- docs/pages/x/api/charts/axis-config.json | 2 +- docs/pages/x/api/charts/bar-chart-pro.json | 17 +- .../x/api/charts/chart-container-pro.json | 17 +- docs/pages/x/api/charts/heatmap.json | 4 +- docs/pages/x/api/charts/line-chart-pro.json | 17 +- .../pages/x/api/charts/scatter-chart-pro.json | 17 +- .../charts/bar-chart-pro/bar-chart-pro.json | 7 +- .../chart-container-pro.json | 7 +- .../charts/line-chart-pro/line-chart-pro.json | 7 +- .../scatter-chart-pro/scatter-chart-pro.json | 7 +- .../src/BarChartPro/BarChartPro.tsx | 20 +-- .../ChartContainerPro/ChartContainerPro.tsx | 20 +-- packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 4 +- .../src/LineChartPro/LineChartPro.tsx | 20 +-- .../src/ScatterChartPro/ScatterChartPro.tsx | 20 +-- packages/x-charts-pro/tsconfig.json | 6 +- packages/x-charts/src/Gauge/Gauge.test.tsx | 2 +- .../ChartDataProvider/ChartDataProvider.tsx | 150 +----------------- .../corePlugins/useChartSeries/index.ts | 2 +- .../createAxisFilterMapper.ts | 9 +- .../useChartCartesianAxis/getAxisExtremum.ts | 2 +- 21 files changed, 36 insertions(+), 321 deletions(-) diff --git a/docs/pages/x/api/charts/axis-config.json b/docs/pages/x/api/charts/axis-config.json index d5d5f7117ac4..9ecbf48e9014 100644 --- a/docs/pages/x/api/charts/axis-config.json +++ b/docs/pages/x/api/charts/axis-config.json @@ -36,6 +36,6 @@ "valueFormatter": { "type": { "description": "(value: V, context: AxisValueFormatterContext) => string" } }, - "zoom": { "type": { "description": "boolean | ZoomOptions" }, "isProPlan": true } + "zoom": { "type": { "description": "boolean | ZoomOption" }, "isProPlan": true } } } diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index 239d6c46f969..9eb4f5472810 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -74,13 +74,6 @@ "describedArgs": ["event", "barItemIdentifier"] } }, - "onZoomChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(zoomData: Array) => void", - "describedArgs": ["zoomData"] - } - }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -100,19 +93,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" - } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } } }, diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index 45a1eab9f7fd..bab8cc8f9c73 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -27,26 +27,19 @@ "describedArgs": ["highlightedItem"] } }, - "onZoomChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(zoomData: Array) => void", - "describedArgs": ["zoomData"] - } - }, "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, "skipAnimation": { "type": { "name": "bool" } }, "width": { "type": { "name": "number" } }, "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zAxis": { @@ -54,12 +47,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "ChartContainerPro", diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index eaa5e5cdc0b5..43da11376cb8 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -7,14 +7,14 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index 20cae716d808..bdeb28662cdb 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -67,13 +67,6 @@ }, "onLineClick": { "type": { "name": "func" } }, "onMarkClick": { "type": { "name": "func" } }, - "onZoomChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(zoomData: Array) => void", - "describedArgs": ["zoomData"] - } - }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -93,19 +86,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" - } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } } }, diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index 715f9261a00c..f52fb073e388 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -63,13 +63,6 @@ "describedArgs": ["event", "scatterItemIdentifier"] } }, - "onZoomChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(zoomData: Array) => void", - "describedArgs": ["zoomData"] - } - }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -90,13 +83,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode?: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zAxis": { @@ -104,12 +97,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "ScatterChartPro", diff --git a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json index 9cc3519bbf28..83f1f673b7dc 100644 --- a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json +++ b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json @@ -56,10 +56,6 @@ "barItemIdentifier": "The bar item identifier." } }, - "onZoomChange": { - "description": "Callback fired when the zoom has changed.", - "typeDescriptions": { "zoomData": "Updated zoom data." } - }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -82,8 +78,7 @@ }, "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "zoom": { "description": "The list of zoom data related to each axis." } + } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json index efa8c876bb1e..b2a482ebb7fc 100644 --- a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json +++ b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json @@ -24,10 +24,6 @@ "description": "The callback fired when the highlighted item changes.", "typeDescriptions": { "highlightedItem": "The newly highlighted item." } }, - "onZoomChange": { - "description": "Callback fired when the zoom has changed.", - "typeDescriptions": { "zoomData": "Updated zoom data." } - }, "series": { "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." }, @@ -43,8 +39,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json index e247d0464564..958fa4e9d53f 100644 --- a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json +++ b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json @@ -53,10 +53,6 @@ }, "onLineClick": { "description": "Callback fired when a line element is clicked." }, "onMarkClick": { "description": "Callback fired when a mark element is clicked." }, - "onZoomChange": { - "description": "Callback fired when the zoom has changed.", - "typeDescriptions": { "zoomData": "Updated zoom data." } - }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -77,8 +73,7 @@ }, "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "zoom": { "description": "The list of zoom data related to each axis." } + } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json index d62674842fb5..b8aef3d5b557 100644 --- a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json +++ b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json @@ -47,10 +47,6 @@ "scatterItemIdentifier": "The scatter item identifier." } }, - "onZoomChange": { - "description": "Callback fired when the zoom has changed.", - "typeDescriptions": { "zoomData": "Updated zoom data." } - }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -77,8 +73,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 87afc249f898..b1196c913abe 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -241,12 +241,6 @@ BarChartPro.propTypes = { * @param {BarItemIdentifier} barItemIdentifier The bar item identifier. */ onItemClick: PropTypes.func, - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -364,7 +358,7 @@ BarChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -450,7 +444,7 @@ BarChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -462,16 +456,6 @@ BarChartPro.propTypes = { ]), }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { BarChartPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 95b7c155db42..7f8afa74f3a7 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -87,12 +87,6 @@ ChartContainerPro.propTypes = { * @param {HighlightItemData | null} highlightedItem The newly highlighted item. */ onHighlightChange: PropTypes.func, - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange: PropTypes.func, plugins: PropTypes.arrayOf(PropTypes.func.isRequired), /** * The array of series to display. @@ -190,7 +184,7 @@ ChartContainerPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -276,7 +270,7 @@ ChartContainerPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -327,16 +321,6 @@ ChartContainerPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { ChartContainerPro }; diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index ea8758a3d598..4d0565f798e9 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -401,7 +401,7 @@ Heatmap.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -489,7 +489,7 @@ Heatmap.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index f97e2259bb3f..d45d024fd8df 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -313,12 +313,6 @@ LineChartPro.propTypes = { * Callback fired when a mark element is clicked. */ onMarkClick: PropTypes.func, - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -436,7 +430,7 @@ LineChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -522,7 +516,7 @@ LineChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -534,16 +528,6 @@ LineChartPro.propTypes = { ]), }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { LineChartPro }; diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index b90ae392e388..796a8f2cde5d 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -174,12 +174,6 @@ ScatterChartPro.propTypes = { * @param {ScatterItemIdentifier} scatterItemIdentifier The scatter item identifier. */ onItemClick: PropTypes.func, - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -302,7 +296,7 @@ ScatterChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -388,7 +382,7 @@ ScatterChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']), + filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -439,16 +433,6 @@ ScatterChartPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { ScatterChartPro }; diff --git a/packages/x-charts-pro/tsconfig.json b/packages/x-charts-pro/tsconfig.json index 7c877b814868..680b4966d88e 100644 --- a/packages/x-charts-pro/tsconfig.json +++ b/packages/x-charts-pro/tsconfig.json @@ -10,5 +10,9 @@ ], "noImplicitAny": false }, - "include": ["src/**/*", "../../test/utils/addChaiAssertions.ts", "../x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts"] + "include": [ + "src/**/*", + "../../test/utils/addChaiAssertions.ts", + "../x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts" + ] } diff --git a/packages/x-charts/src/Gauge/Gauge.test.tsx b/packages/x-charts/src/Gauge/Gauge.test.tsx index cb7b79790456..f3d7cf533b0b 100644 --- a/packages/x-charts/src/Gauge/Gauge.test.tsx +++ b/packages/x-charts/src/Gauge/Gauge.test.tsx @@ -5,7 +5,7 @@ import { Gauge } from '@mui/x-charts/Gauge'; describe('', () => { const { render } = createRenderer(); - describeConformance(, () => ({ + describeConformance(, () => ({ classes: {} as any, inheritComponent: 'svg', render, diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 971963ef943b..7eacee188658 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -133,155 +133,7 @@ ChartDataProvider.propTypes = { /** * The width of the chart in px. If not defined, it takes the width of the parent element. */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), + width: PropTypes.any, /** * The configuration of the z-axes. */ diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts index 3bbbfba2164e..3e328aa314ab 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/index.ts @@ -3,6 +3,6 @@ export type { UseChartSeriesSignature, UseChartSeriesParameters, UseChartSeriesDefaultizedParameters, - ProcessedSeries + ProcessedSeries, } from './useChartSeries.types'; export * from './useChartSeries.selectors'; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts index 77aa7a0ee3af..4eb52d14dacf 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts @@ -6,13 +6,8 @@ import { ProcessedSeries } from '../../corePlugins/useChartSeries'; import { AxisConfig, ScaleName } from '../../../../models'; import { ChartSeriesConfig } from '../../models/seriesConfig'; import { getAxisExtremum } from './getAxisExtremum'; -import { - DefaultizedZoomOption, - ExtremumFilter, - GetZoomAxisFilters, - ZoomAxisFilters, - ZoomData, -} from './useChartCartesianAxis.types'; +import { DefaultizedZoomOption, ExtremumFilter } from './useChartCartesianAxis.types'; +import { GetZoomAxisFilters, ZoomAxisFilters, ZoomData } from './zoom.types'; type CreateAxisFilterMapperParams = { zoomMap: Map; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts index 5237c3391b49..bacba0c9e899 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/getAxisExtremum.ts @@ -6,7 +6,7 @@ import { CartesianExtremumGetter, CartesianExtremumGetterResult, } from '../../models/seriesConfig/extremumGetter.types'; -import { GetZoomAxisFilters } from './useChartCartesianAxis.types'; +import { GetZoomAxisFilters } from './zoom.types'; import { isCartesianSeriesType } from '../../../isCartesian'; const axisExtremumCallback = ( From 4421932f703dff900d615798cd1619b61ce636db Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 12:17:33 +0100 Subject: [PATCH 13/32] fix-ts --- .../src/BarChartPro/BarChartPro.tsx | 11 +- .../ChartContainerPro/ChartContainerPro.tsx | 358 +++--------------- .../useChartContainerProProps.ts | 42 +- packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 7 +- packages/x-charts-pro/src/Heatmap/plugin.ts | 7 +- .../src/LineChartPro/LineChartPro.tsx | 11 +- .../src/ScatterChartPro/ScatterChartPro.tsx | 9 +- .../ChartDataProviderPro.tsx | 44 --- .../src/context/ChartDataProviderPro/index.ts | 1 - .../useChartDataProviderProProps.ts | 40 -- .../src/context/ZoomProvider/ZoomContext.ts | 20 - .../src/context/ZoomProvider/ZoomProvider.tsx | 67 ---- .../src/context/ZoomProvider/ZoomSetup.ts | 17 - .../src/context/ZoomProvider/index.ts | 3 - .../ZoomProvider/initializeZoomData.ts | 10 - .../src/context/ZoomProvider/useSetupZoom.ts | 11 +- packages/x-charts-pro/src/context/index.ts | 4 - packages/x-charts-pro/src/hooks/index.ts | 1 + packages/x-charts-pro/src/hooks/zoom/index.ts | 1 + .../zoom/useZoomIsInteracting.ts} | 3 +- packages/x-charts-pro/src/index.ts | 3 - .../useChartProZoom/useChartProZoom.ts | 10 +- packages/x-charts/src/BarChart/BarChart.tsx | 2 +- .../x-charts/src/BarChart/useBarChartProps.ts | 2 +- .../src/ChartContainer/ChartContainer.tsx | 284 +------------- .../ChartContainer/useChartContainerProps.ts | 21 +- .../src/LineChart/useLineChartProps.ts | 2 +- .../src/ScatterChart/useScatterChartProps.ts | 2 +- .../ChartDataProvider/ChartDataProvider.tsx | 9 +- .../context/ChartProvider/ChartProvider.tsx | 14 +- .../useChartCartesianAxis.ts | 2 +- .../useChartCartesianAxis/zoom.types.ts | 2 +- .../x-charts/src/internals/store/useCharts.ts | 3 +- 33 files changed, 167 insertions(+), 856 deletions(-) delete mode 100644 packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx delete mode 100644 packages/x-charts-pro/src/context/ChartDataProviderPro/index.ts delete mode 100644 packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/index.ts delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts delete mode 100644 packages/x-charts-pro/src/context/index.ts create mode 100644 packages/x-charts-pro/src/hooks/zoom/index.ts rename packages/x-charts-pro/src/{context/ZoomProvider/useZoom.ts => hooks/zoom/useZoomIsInteracting.ts} (72%) diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index b1196c913abe..5931053b49d9 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -12,10 +12,8 @@ import { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useBarChartProps } from '@mui/x-charts/internals'; -import { ChartContainerPro } from '../ChartContainerPro'; -import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; -import { useZoomIsInteracting } from '../context/ZoomProvider/useZoom'; -import { ZoomProps } from '../context/ZoomProvider'; +import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro'; +import { useZoomIsInteracting } from '../hooks/zoom'; function BarChartPlotZoom(props: BarPlotProps) { const isInteracting = useZoomIsInteracting(); @@ -63,7 +61,9 @@ BarChartPlotZoom.propTypes = { slots: PropTypes.object, } as any; -export interface BarChartProProps extends BarChartProps, ZoomProps {} +export interface BarChartProProps + extends BarChartProps, + Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** * Demos: @@ -111,7 +111,6 @@ const BarChartPro = React.forwardRef(function BarChartPro( {!props.hideLegend && } {!props.loading && } - {children} ); diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 7f8afa74f3a7..94994b0bb871 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -1,326 +1,66 @@ 'use client'; import * as React from 'react'; -import PropTypes from 'prop-types'; import type {} from '../typeOverloads'; import { Watermark } from '@mui/x-license/Watermark'; -import { ChartContainerProps } from '@mui/x-charts/ChartContainer'; -import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; +import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; +import { ChartsSurface, ChartsSurfaceProps } from '@mui/x-charts/ChartsSurface'; +import { ChartDataProvider, ChartDataProviderProps } from '@mui/x-charts/context'; +import { ChartSeriesType, UseChartCartesianAxisSignature } from '@mui/x-charts/internals'; import { getReleaseInfo } from '../internals/utils/releaseInfo'; -import { ChartDataProviderPro } from '../context/ChartDataProviderPro'; -import { ZoomProps } from '../context/ZoomProvider'; import { useChartContainerProProps } from './useChartContainerProProps'; +import { UseChartProZoomSignature } from '../internals/plugins/useChartProZoom/useChartProZoom.types'; -export interface ChartContainerProProps extends ChartContainerProps, ZoomProps {} +export interface ChartContainerProProps + extends ChartDataProviderProps< + [UseChartCartesianAxisSignature, UseChartProZoomSignature], + TSeries + >, + ChartsSurfaceProps {} const releaseInfo = getReleaseInfo(); -const ChartContainerPro = React.forwardRef(function ChartContainerPro( - props: ChartContainerProProps, - ref: React.Ref, -) { - const { chartDataProviderProProps, children, chartsSurfaceProps } = useChartContainerProProps( - props, - ref, - ); +/** + * It sets up the data providers as well as the `` for the chart. + * + * This is a combination of both the `ChartDataProvider` and `ChartsSurface` components. + * + * Demos: + * + * - [Composition](http://localhost:3001/x/react-charts/composition/) + * + * API: + * + * - [ChartContainer API](https://mui.com/x/api/charts/chart-container/) + * + * @example + * ```jsx + * + * + * + * + * ``` + */ +const ChartContainerPro = React.forwardRef(function ChartContainerProInner< + TSeries extends ChartSeriesType = ChartSeriesType, +>(props: ChartContainerProProps, ref: React.Ref) { + const { chartDataProviderProProps, children, chartsSurfaceProps } = + useChartContainerProProps(props, ref); + + useLicenseVerifier('x-charts-pro', releaseInfo); return ( - + , UseChartProZoomSignature], any> + {...chartDataProviderProProps} + > {children} - + ); -}); - -ChartContainerPro.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - children: PropTypes.node, - className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset: PropTypes.arrayOf(PropTypes.object), - desc: PropTypes.string, - /** - * If `true`, the charts will not listen to the mouse move event. - * It might break interactive features, but will improve performance. - * @default false - */ - disableAxisListener: PropTypes.bool, - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height: PropTypes.number, - /** - * The item currently highlighted. Turns highlighting into a controlled prop. - */ - highlightedItem: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - }), - /** - * This prop is used to help implement the accessibility logic. - * If you don't provide this prop. It falls back to a randomly generated id. - */ - id: PropTypes.string, - /** - * The margin between the SVG and the drawing area. - * It's used for leaving some space for extra information such as the x- and y-axis or legend. - * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - */ - margin: PropTypes.shape({ - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - top: PropTypes.number, - }), - /** - * The callback fired when the highlighted item changes. - * - * @param {HighlightItemData | null} highlightedItem The newly highlighted item. - */ - onHighlightChange: PropTypes.func, - plugins: PropTypes.arrayOf(PropTypes.func.isRequired), - /** - * The array of series to display. - * Each type of series has its own specificity. - * Please refer to the appropriate docs page to learn more about it. - */ - series: PropTypes.arrayOf(PropTypes.object), - /** - * If `true`, animations are skipped. - * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. - */ - skipAnimation: PropTypes.bool, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - theme: PropTypes.oneOf(['dark', 'light']), - title: PropTypes.string, - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - zoom: PropTypes.oneOfType([ - PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, - maxEnd: PropTypes.number, - maxSpan: PropTypes.number, - minSpan: PropTypes.number, - minStart: PropTypes.number, - panning: PropTypes.bool, - step: PropTypes.number, - }), - PropTypes.bool, - ]), - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - zoom: PropTypes.oneOfType([ - PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, - maxEnd: PropTypes.number, - maxSpan: PropTypes.number, - minSpan: PropTypes.number, - minStart: PropTypes.number, - panning: PropTypes.bool, - step: PropTypes.number, - }), - PropTypes.bool, - ]), - }), - ), - /** - * The configuration of the z-axes. - */ - zAxis: PropTypes.arrayOf( - PropTypes.shape({ - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - id: PropTypes.string, - max: PropTypes.number, - min: PropTypes.number, - }), - ), -} as any; +}) as ( + props: ChartContainerProProps & { ref?: React.ForwardedRef }, +) => React.JSX.Element; export { ChartContainerPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index 1ed9a64b2494..de62cf9ad077 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -1,33 +1,46 @@ 'use client'; import { + ChartDataProviderProps, + ChartPlugin, + ChartSeriesType, useChartCartesianAxis, + UseChartCartesianAxisSignature, useChartContainerProps, UseChartContainerPropsReturnValue, } from '@mui/x-charts/internals'; import * as React from 'react'; -import type { ChartDataProviderProProps } from '../context/ChartDataProviderPro'; import type { ChartContainerProProps } from './ChartContainerPro'; import { useChartProZoom } from '../internals/plugins/useChartProZoom'; +import { UseChartProZoomSignature } from '../internals/plugins/useChartProZoom/useChartProZoom.types'; -export type UseChartContainerProPropsReturnValue = Omit< - UseChartContainerPropsReturnValue, - 'chartDataProviderProps' +export type UseChartContainerProPropsReturnValue = Pick< + UseChartContainerPropsReturnValue, + 'chartsSurfaceProps' | 'children' > & { - chartDataProviderProProps: ChartDataProviderProProps; + chartDataProviderProProps: ChartDataProviderProps< + [UseChartCartesianAxisSignature, UseChartProZoomSignature], + TSeries + >; }; -export const useChartContainerProProps = ( - props: ChartContainerProProps, +export const useChartContainerProProps = ( + props: ChartContainerProProps, ref: React.Ref, -): UseChartContainerProPropsReturnValue => { +): UseChartContainerProPropsReturnValue => { const { zoom, onZoomChange, plugins, ...baseProps } = props; - const chartDataProviderProProps: Pick = { + const chartDataProviderProProps: Pick< + ChartDataProviderProps< + [UseChartCartesianAxisSignature, UseChartProZoomSignature], + TSeries + >, + 'zoom' | 'onZoomChange' + > = { zoom, onZoomChange, }; - const { chartDataProviderProps, chartsSurfaceProps, children } = useChartContainerProps( + const { chartDataProviderProps, chartsSurfaceProps, children } = useChartContainerProps( baseProps, ref, ); @@ -36,8 +49,13 @@ export const useChartContainerProProps = ( chartDataProviderProProps: { ...chartDataProviderProps, ...chartDataProviderProProps, - // eslint-disable-next-line react-compiler/react-compiler - plugins: [useChartCartesianAxis, useChartProZoom], + + plugins: [ + // eslint-disable-next-line react-compiler/react-compiler + useChartCartesianAxis as unknown as ChartPlugin>, + // eslint-disable-next-line react-compiler/react-compiler + useChartProZoom, + ], }, chartsSurfaceProps, children, diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index 4d0565f798e9..0adbe0be250c 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -13,6 +13,7 @@ import { ChartsXAxisProps, ChartsYAxisProps, AxisConfig, + ChartSeriesConfig, } from '@mui/x-charts/internals'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { @@ -101,6 +102,8 @@ const defaultColorMap = interpolateRgbBasis([ '#084081', ]); +const seriesConfig: ChartSeriesConfig<'heatmap'> = { heatmap: heatmapPlugin }; + const Heatmap = React.forwardRef(function Heatmap( inProps: HeatmapProps, ref: React.Ref, @@ -161,9 +164,9 @@ const Heatmap = React.forwardRef(function Heatmap( const Tooltip = props.slots?.tooltip ?? HeatmapTooltip; return ( - ref={ref} - plugins={[heatmapPlugin]} + seriesConfig={seriesConfig} series={series.map((s) => ({ type: 'heatmap', ...s, diff --git a/packages/x-charts-pro/src/Heatmap/plugin.ts b/packages/x-charts-pro/src/Heatmap/plugin.ts index 52177f244abb..0d285736feff 100644 --- a/packages/x-charts-pro/src/Heatmap/plugin.ts +++ b/packages/x-charts-pro/src/Heatmap/plugin.ts @@ -1,11 +1,10 @@ -import { ChartsPlugin } from '@mui/x-charts/internals'; +import { ChartSeriesTypeConfig } from '@mui/x-charts/internals'; import { getBaseExtremum } from './extremums'; import formatter from './formatter'; import getColor from './getColor'; -export const plugin: ChartsPlugin<'heatmap'> = { - seriesType: 'heatmap', - seriesFormatter: formatter, +export const plugin: ChartSeriesTypeConfig<'heatmap'> = { + seriesProcessor: formatter, colorProcessor: getColor, xExtremumGetter: getBaseExtremum, yExtremumGetter: getBaseExtremum, diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index d45d024fd8df..ed2086784e81 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -21,10 +21,8 @@ import { ChartsLegend } from '@mui/x-charts/ChartsLegend'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { useLineChartProps } from '@mui/x-charts/internals'; -import { ChartContainerPro } from '../ChartContainerPro'; -import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; -import { useZoomIsInteracting } from '../context/ZoomProvider/useZoom'; -import { ZoomProps } from '../context/ZoomProvider'; +import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro'; +import { useZoomIsInteracting } from '../hooks/zoom'; function AreaPlotZoom(props: AreaPlotProps) { const isInteracting = useZoomIsInteracting(); @@ -131,7 +129,9 @@ MarkPlotZoom.propTypes = { slots: PropTypes.object, } as any; -export interface LineChartProProps extends LineChartProps, ZoomProps {} +export interface LineChartProProps + extends LineChartProps, + Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** * Demos: @@ -187,7 +187,6 @@ const LineChartPro = React.forwardRef(function LineChartPro( {!props.hideLegend && } {!props.loading && } - {children} ); diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index 796a8f2cde5d..d780e91be85c 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -12,11 +12,11 @@ import { ChartsLegend } from '@mui/x-charts/ChartsLegend'; import { ChartsAxisHighlight } from '@mui/x-charts/ChartsAxisHighlight'; import { ChartsTooltip } from '@mui/x-charts/ChartsTooltip'; import { useScatterChartProps } from '@mui/x-charts/internals'; -import { ChartContainerPro } from '../ChartContainerPro'; -import { ZoomSetup } from '../context/ZoomProvider/ZoomSetup'; -import { ZoomProps } from '../context/ZoomProvider'; +import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro'; -export interface ScatterChartProProps extends ScatterChartProps, ZoomProps {} +export interface ScatterChartProProps + extends ScatterChartProps, + Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** * Demos: @@ -63,7 +63,6 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( {!props.hideLegend && } {!props.loading && } - {children}
diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx deleted file mode 100644 index 876843e5c6f3..000000000000 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx +++ /dev/null @@ -1,44 +0,0 @@ -'use client'; -import * as React from 'react'; -import { - ChartDataProviderProps, - AnimationProvider, - ChartProvider, - UseChartCartesianAxisSignature, -} from '@mui/x-charts/internals'; -import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; -import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; -import { getReleaseInfo } from '../../internals/utils/releaseInfo'; -import { ZoomProps } from '../ZoomProvider'; -import { useChartContainerProProps } from './useChartDataProviderProProps'; -import { UseChartProZoomSignature } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; - -const releaseInfo = getReleaseInfo(); - -export interface ChartDataProviderProProps - extends ChartDataProviderProps<[UseChartCartesianAxisSignature, UseChartProZoomSignature]>, - ZoomProps {} - -function ChartDataProviderPro(props: ChartDataProviderProProps) { - const { - zAxisContextProps, - highlightedProviderProps, - animationProviderProps, - chartProviderProps, - children, - } = useChartContainerProProps(props); - - useLicenseVerifier('x-charts-pro', releaseInfo); - - return ( - - - - {children} - - - - ); -} - -export { ChartDataProviderPro }; diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/index.ts b/packages/x-charts-pro/src/context/ChartDataProviderPro/index.ts deleted file mode 100644 index 1e34719a86a3..000000000000 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './ChartDataProviderPro'; diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts b/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts deleted file mode 100644 index 52a25d542ff5..000000000000 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/useChartDataProviderProProps.ts +++ /dev/null @@ -1,40 +0,0 @@ -'use client'; -import { useChartDataProviderProps } from '@mui/x-charts/internals'; -import { ZoomProviderProps } from '../ZoomProvider'; -import type { ChartDataProviderProProps } from './ChartDataProviderPro'; - -export const useChartContainerProProps = (props: ChartDataProviderProProps) => { - const { zoom, onZoomChange, ...baseProps } = props; - - const { - children, - chartProviderProps, - seriesProviderProps, - cartesianProviderProps, - zAxisContextProps, - highlightedProviderProps, - pluginProviderProps, - animationProviderProps, - xAxis, - yAxis, - } = useChartDataProviderProps(baseProps); - - const zoomProviderProps: Omit = { - zoom, - onZoomChange, - xAxis, - yAxis, - }; - - return { - zoomProviderProps, - children, - pluginProviderProps, - seriesProviderProps, - cartesianProviderProps, - zAxisContextProps, - highlightedProviderProps, - chartProviderProps, - animationProviderProps, - }; -}; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts b/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts deleted file mode 100644 index a4cecd94d228..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/ZoomContext.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -import { Initializable } from '@mui/x-charts/internals'; -import { ZoomState } from './Zoom.types'; - -export const ZoomContext = React.createContext>({ - isInitialized: false, - data: { - isZoomEnabled: false, - isPanEnabled: false, - options: {}, - zoomData: [], - setZoomData: () => {}, - isInteracting: false, - setIsInteracting: () => {}, - }, -}); - -if (process.env.NODE_ENV !== 'production') { - ZoomContext.displayName = 'ZoomContext'; -} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx b/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx deleted file mode 100644 index cd8940001918..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/ZoomProvider.tsx +++ /dev/null @@ -1,67 +0,0 @@ -'use client'; -import * as React from 'react'; -import useControlled from '@mui/utils/useControlled'; -import { Initializable } from '@mui/x-charts/internals'; -import { ZoomContext } from './ZoomContext'; -import { defaultizeZoom } from './defaultizeZoom'; -import { ZoomData, ZoomProviderProps, ZoomState } from './Zoom.types'; -import { initializeZoomData } from './initializeZoomData'; - -export function ZoomProvider({ children, xAxis, yAxis, zoom, onZoomChange }: ZoomProviderProps) { - const [isInteracting, setIsInteracting] = React.useState(false); - - const options = React.useMemo( - () => - [...defaultizeZoom(xAxis, 'x'), ...defaultizeZoom(yAxis, 'y')].reduce( - (acc, v) => { - acc[v.axisId] = v; - return acc; - }, - {} as ZoomState['options'], - ), - [xAxis, yAxis], - ); - - // Default zoom data is initialized only once when uncontrolled. If the user changes the options - // after the initial render, the zoom data will not be updated until the next zoom interaction. - // This is required to avoid warnings about controlled/uncontrolled components. - const defaultZoomData = React.useRef(initializeZoomData(options)); - - const [zoomData, setZoomData] = useControlled({ - controlled: zoom, - // eslint-disable-next-line react-compiler/react-compiler - default: defaultZoomData.current, - name: 'ZoomProvider', - state: 'zoom', - }); - - const setZoomDataCallback = React.useCallback( - (newZoomData) => { - setZoomData(newZoomData); - onZoomChange?.(newZoomData); - }, - [setZoomData, onZoomChange], - ); - - const value = React.useMemo>( - () => ({ - isInitialized: true, - data: { - isZoomEnabled: Object.keys(options).length > 0, - isPanEnabled: isPanEnabled(options), - options, - zoomData, - setZoomData: setZoomDataCallback, - isInteracting, - setIsInteracting, - }, - }), - [zoomData, isInteracting, setIsInteracting, options, setZoomDataCallback], - ); - - return {children}; -} - -function isPanEnabled(options: Record): boolean { - return Object.values(options).some((v) => v.panning) || false; -} diff --git a/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts b/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts deleted file mode 100644 index 775b173dabdf..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/ZoomSetup.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { useSetupPan } from './useSetupPan'; -import { useSetupZoom } from './useSetupZoom'; - -/** - * Sets up the zoom functionality if using composition or a custom chart. - * - * Simply add this component at the same level as the chart component to enable zooming and panning. - * - * See: [Composition](https://mui.com/x/react-charts/composition/) - */ -function ZoomSetup() { - useSetupZoom(); - useSetupPan(); - return null; -} - -export { ZoomSetup }; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/index.ts b/packages/x-charts-pro/src/context/ZoomProvider/index.ts deleted file mode 100644 index 0ecf380a2aed..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './ZoomContext'; -export * from './ZoomProvider'; -export * from './Zoom.types'; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts b/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts deleted file mode 100644 index 101473a50f41..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/initializeZoomData.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { AxisId, DefaultizedZoomOption } from '@mui/x-charts/internals'; - -// It is helpful to avoid the need to provide the possibly auto-generated id for each axis. -export const initializeZoomData = (options: Record) => { - return Object.values(options).map(({ axisId, minStart: start, maxEnd: end }) => ({ - axisId, - start, - end, - })); -}; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts index 1371b02788ae..668b8e4b4515 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts +++ b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts @@ -3,6 +3,7 @@ import * as React from 'react'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; import { AxisId, + ChartSeriesType, DefaultizedZoomOption, getSVGPoint, UseChartCartesianAxisSignature, @@ -11,7 +12,7 @@ import { useStore, ZoomData, } from '@mui/x-charts/internals'; -import { UseChartProZoomState } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; +import { UseChartProZoomSignature } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; import { selectorChartZoomOptions } from '../../internals/plugins/useChartProZoom'; /** @@ -24,7 +25,7 @@ const zoomAtPoint = ( centerRatio: number, scaleRatio: number, currentZoomData: ZoomData, - options: Record, + options: DefaultizedZoomOption, ) => { const MIN_RANGE = options.minStart; const MAX_RANGE = options.maxEnd; @@ -64,8 +65,8 @@ const zoomAtPoint = ( return [newMinRange, newMaxRange]; }; -export const useSetupZoom = () => { - const store = useStore<[UseChartCartesianAxisSignature, UseChartProZoomState]>(); +export const useSetupZoom = () => { + const store = useStore<[UseChartCartesianAxisSignature, UseChartProZoomSignature]>(); const options = useSelector(store, selectorChartZoomOptions); const isZoomEnabled = Object.keys(options).length > 0; @@ -284,7 +285,7 @@ function isSpanValid( minRange: number, maxRange: number, isZoomIn: boolean, - option: DefaultizedZoomOptions, + option: DefaultizedZoomOption, ) { const newSpanPercent = maxRange - minRange; diff --git a/packages/x-charts-pro/src/context/index.ts b/packages/x-charts-pro/src/context/index.ts deleted file mode 100644 index d0634736be8a..000000000000 --- a/packages/x-charts-pro/src/context/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// # Zoom & Pan -export type { ZoomOptions, ZoomData, ZoomProps, ZoomState } from './ZoomProvider/Zoom.types'; -export * from './ZoomProvider/useZoom'; -export * from './ZoomProvider/ZoomSetup'; diff --git a/packages/x-charts-pro/src/hooks/index.ts b/packages/x-charts-pro/src/hooks/index.ts index efe4654a2e1f..a858444b9d94 100644 --- a/packages/x-charts-pro/src/hooks/index.ts +++ b/packages/x-charts-pro/src/hooks/index.ts @@ -1 +1,2 @@ export { useHeatmapSeries as unstable_useHeatmapSeries } from './useSeries'; +export * from './zoom'; diff --git a/packages/x-charts-pro/src/hooks/zoom/index.ts b/packages/x-charts-pro/src/hooks/zoom/index.ts new file mode 100644 index 000000000000..79f7e09a5779 --- /dev/null +++ b/packages/x-charts-pro/src/hooks/zoom/index.ts @@ -0,0 +1 @@ +export * from './useZoomIsInteracting'; diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts b/packages/x-charts-pro/src/hooks/zoom/useZoomIsInteracting.ts similarity index 72% rename from packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts rename to packages/x-charts-pro/src/hooks/zoom/useZoomIsInteracting.ts index 2ac4bac6fad5..65370c59c47b 100644 --- a/packages/x-charts-pro/src/context/ZoomProvider/useZoom.ts +++ b/packages/x-charts-pro/src/hooks/zoom/useZoomIsInteracting.ts @@ -1,6 +1,7 @@ 'use client'; import { useSelector, useStore } from '@mui/x-charts/internals'; import { selectorChartZoomIsInteracting } from '../../internals/plugins/useChartProZoom'; +import { UseChartProZoomSignature } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; /** * Get access to the zoom state. @@ -8,7 +9,7 @@ import { selectorChartZoomIsInteracting } from '../../internals/plugins/useChart * @returns {boolean} Inform the zoom is interacting. */ export function useZoomIsInteracting(): boolean { - const store = useStore<[UseChartProCartesianAxisSignature]>(); + const store = useStore<[UseChartProZoomSignature]>(); const isInteracting = useSelector(store, selectorChartZoomIsInteracting); return isInteracting; diff --git a/packages/x-charts-pro/src/index.ts b/packages/x-charts-pro/src/index.ts index 932b0136d8d3..c2bd03b9ef5e 100644 --- a/packages/x-charts-pro/src/index.ts +++ b/packages/x-charts-pro/src/index.ts @@ -32,6 +32,3 @@ export * from './ChartContainerPro'; export * from './ScatterChartPro'; export * from './BarChartPro'; export * from './LineChartPro'; - -// Pro context -export * from './context'; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts index e2aa79b7f095..c93abae747f3 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts @@ -4,7 +4,15 @@ import { ChartPlugin, AxisId, DefaultizedZoomOption } from '@mui/x-charts/intern import { UseChartProZoomSignature } from './useChartProZoom.types'; import { defaultizeZoom } from './defaultizeZoom'; import { createZoomMap } from './useChartProZoom.utils'; -import { initializeZoomData } from '../../../context/ZoomProvider/initializeZoomData'; + +// It is helpful to avoid the need to provide the possibly auto-generated id for each axis. +function initializeZoomData(options: Record) { + return Object.values(options).map(({ axisId, minStart: start, maxEnd: end }) => ({ + axisId, + start, + end, + })); +} export const useChartProZoom: ChartPlugin = ({ store, models }) => { useEnhancedEffect(() => { diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index 39048a67c405..d42550a7ff06 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -40,7 +40,7 @@ export interface BarChartSlotProps ChartsTooltipSlotProps {} export interface BarChartProps - extends Omit, + extends Omit, 'series' | 'plugins' | 'zAxis'>, Omit, Omit, Omit, diff --git a/packages/x-charts/src/BarChart/useBarChartProps.ts b/packages/x-charts/src/BarChart/useBarChartProps.ts index ab65c93ad40e..a9ff9a58d82d 100644 --- a/packages/x-charts/src/BarChart/useBarChartProps.ts +++ b/packages/x-charts/src/BarChart/useBarChartProps.ts @@ -68,7 +68,7 @@ export const useBarChartProps = (props: BarChartProps) => { ), } as const; - const chartContainerProps: ChartContainerProps = { + const chartContainerProps: Omit, 'plugins'> = { ...rest, series: series.map((s) => ({ type: 'bar' as const, diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index b825b0166b0f..3656d66e6780 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -1,6 +1,5 @@ 'use client'; import * as React from 'react'; -import PropTypes from 'prop-types'; import { ChartSeriesType } from '../models/seriesType/config'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; import { useChartContainerProps } from './useChartContainerProps'; @@ -8,7 +7,10 @@ import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; import { UseChartCartesianAxisSignature } from '../internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types'; export interface ChartContainerProps - extends ChartDataProviderProps<[UseChartCartesianAxisSignature]>, + extends Omit< + ChartDataProviderProps<[UseChartCartesianAxisSignature], SeriesType>, + 'children' + >, ChartsSurfaceProps {} /** @@ -35,8 +37,8 @@ export interface ChartContainerProps * ``` */ -const ChartContainer = React.forwardRef(function ChartContainer( - props: ChartContainerProps, +const ChartContainer = React.forwardRef(function ChartContainer( + props: ChartContainerProps, ref: React.Ref, ) { const { chartDataProviderProps, children, chartsSurfaceProps } = useChartContainerProps( @@ -45,278 +47,12 @@ const ChartContainer = React.forwardRef(function ChartContainer( ); return ( - {...chartDataProviderProps}> + ], any> {...chartDataProviderProps}> {children} ); -}); - -ChartContainer.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - children: PropTypes.node, - className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset: PropTypes.arrayOf(PropTypes.object), - desc: PropTypes.string, - /** - * If `true`, the charts will not listen to the mouse move event. - * It might break interactive features, but will improve performance. - * @default false - */ - disableAxisListener: PropTypes.bool, - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height: PropTypes.number, - /** - * The item currently highlighted. Turns highlighting into a controlled prop. - */ - highlightedItem: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - }), - /** - * This prop is used to help implement the accessibility logic. - * If you don't provide this prop. It falls back to a randomly generated id. - */ - id: PropTypes.string, - /** - * The margin between the SVG and the drawing area. - * It's used for leaving some space for extra information such as the x- and y-axis or legend. - * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - */ - margin: PropTypes.shape({ - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - top: PropTypes.number, - }), - /** - * The callback fired when the highlighted item changes. - * - * @param {HighlightItemData | null} highlightedItem The newly highlighted item. - */ - onHighlightChange: PropTypes.func, - plugins: PropTypes.arrayOf(PropTypes.func.isRequired), - /** - * The array of series to display. - * Each type of series has its own specificity. - * Please refer to the appropriate docs page to learn more about it. - */ - series: PropTypes.arrayOf(PropTypes.object), - /** - * If `true`, animations are skipped. - * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. - */ - skipAnimation: PropTypes.bool, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - theme: PropTypes.oneOf(['dark', 'light']), - title: PropTypes.string, - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the z-axes. - */ - zAxis: PropTypes.arrayOf( - PropTypes.shape({ - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - id: PropTypes.string, - max: PropTypes.number, - min: PropTypes.number, - }), - ), -} as any; +}) as ( + props: ChartContainerProps & { ref?: React.ForwardedRef }, +) => React.JSX.Element; export { ChartContainer }; diff --git a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts index 4355193caf50..281a464ed2ec 100644 --- a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts +++ b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts @@ -7,17 +7,21 @@ import { useChartCartesianAxis, UseChartCartesianAxisSignature, } from '../internals/plugins/featurePlugins/useChartCartesianAxis'; +import { ChartSeriesType } from '../models/seriesType/config'; -export type UseChartContainerPropsReturnValue = { - chartDataProviderProps: ChartDataProviderProps<[UseChartCartesianAxisSignature]>; +export type UseChartContainerPropsReturnValue = { + chartDataProviderProps: ChartDataProviderProps< + [UseChartCartesianAxisSignature], + TSeries + >; chartsSurfaceProps: ChartsSurfaceProps & { ref: React.Ref }; children: React.ReactNode; }; -export const useChartContainerProps = ( - props: ChartContainerProps, +export const useChartContainerProps = ( + props: ChartContainerProps, ref: React.Ref, -): UseChartContainerPropsReturnValue => { +): UseChartContainerPropsReturnValue => { const { width, height, @@ -48,7 +52,10 @@ export const useChartContainerProps = ( ...other, }; - const chartDataProviderProps: ChartDataProviderProps<[UseChartCartesianAxisSignature]> = { + const chartDataProviderProps: Omit< + ChartDataProviderProps<[UseChartCartesianAxisSignature], TSeries>, + 'children' + > = { margin, series, colors, @@ -61,7 +68,7 @@ export const useChartContainerProps = ( skipAnimation, width, height, - plugins: [useChartCartesianAxis], + plugins: [useChartCartesianAxis as any], }; return { diff --git a/packages/x-charts/src/LineChart/useLineChartProps.ts b/packages/x-charts/src/LineChart/useLineChartProps.ts index 05cef6fc627b..cd5605229fd2 100644 --- a/packages/x-charts/src/LineChart/useLineChartProps.ts +++ b/packages/x-charts/src/LineChart/useLineChartProps.ts @@ -60,7 +60,7 @@ export const useLineChartProps = (props: LineChartProps) => { const id = useId(); const clipPathId = `${id}-clip-path`; - const chartContainerProps: ChartContainerProps = { + const chartContainerProps: Omit, 'plugins'> = { ...other, series: series.map((s) => ({ disableHighlight: !!disableLineItemHighlight, diff --git a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts index 0399f0543a96..67212a81b531 100644 --- a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts +++ b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts @@ -48,7 +48,7 @@ export const useScatterChartProps = (props: ScatterChartProps) => { ...other } = props; - const chartContainerProps: ChartContainerProps = { + const chartContainerProps: Omit, 'plugins'> = { ...other, series: series.map((s) => ({ type: 'scatter' as const, ...s })), width, diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 7eacee188658..73f7d34e77e2 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -22,10 +22,11 @@ export type ChartDataProviderProps< AnimationProviderProps & ChartProviderProps['pluginParams'], 'children' -> & { - plugins?: ChartProviderProps['plugins']; - children?: React.ReactNode; -}; +> & + Pick, 'seriesConfig'> & { + plugins?: ChartProviderProps['plugins']; + children?: React.ReactNode; + }; /** * Orchestrates the data providers for the chart components and hooks. diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx index aadba0237c3b..525f8696a151 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx @@ -3,7 +3,10 @@ import * as React from 'react'; import { useCharts } from '../../internals/store/useCharts'; import { ChartProviderProps } from './ChartProvider.types'; import { ChartContext } from './ChartContext'; -import { ChartAnyPluginSignature } from '../../internals/plugins/models'; +import { + ChartAnyPluginSignature, + ConvertSignaturesIntoPlugins, +} from '../../internals/plugins/models'; import { ChartSeriesConfig } from '../../internals/plugins/models/seriesConfig'; import { plugin as barPlugin } from '../../BarChart/plugin'; import { plugin as scatterPlugin } from '../../ScatterChart/plugin'; @@ -22,9 +25,14 @@ function ChartProvider< TSignatures extends readonly ChartAnyPluginSignature[], TSeriesType extends ChartSeriesType, >(props: ChartProviderProps) { - const { children, plugins = [], pluginParams = {}, seriesConfig = defaultSeriesConfig } = props; + const { + children, + plugins = [] as ConvertSignaturesIntoPlugins, + pluginParams = {}, + seriesConfig = defaultSeriesConfig as ChartSeriesConfig, + } = props; - const { contextValue } = useCharts(plugins, pluginParams, seriesConfig); + const { contextValue } = useCharts(plugins, pluginParams, seriesConfig); return {children}; } diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts index 0e6616264445..6e5e57972302 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.ts @@ -1,13 +1,13 @@ 'use client'; import * as React from 'react'; import { ChartPlugin } from '../../models'; +import { ChartSeriesType } from '../../../../models/seriesType/config'; import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; import { blueberryTwilightPalette } from '../../../../colorPalettes'; import { useSelector } from '../../../store/useSelector'; import { selectorChartDrawingArea } from '../../corePlugins/useChartDimensions/useChartDimensions.selectors'; import { selectorChartSeriesState } from '../../corePlugins/useChartSeries/useChartSeries.selectors'; import { defaultizeAxis } from './defaultizeAxis'; -import { ChartSeriesType } from '../../../../models/seriesType/config'; export const useChartCartesianAxis: ChartPlugin< UseChartCartesianAxisSignature diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts index d67db2194e7e..2403aed090db 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/zoom.types.ts @@ -4,7 +4,7 @@ import type { ExtremumFilter } from './useChartCartesianAxis.types'; export type ZoomData = { axisId: AxisId; start: number; end: number }; -export type ZoomFilterMode = 'keep' | 'discard' | 'empty'; +export type ZoomFilterMode = 'keep' | 'discard'; export interface ZoomOption { filterMode: ZoomFilterMode; } diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index 915a889c7ecc..09ce3094f2d2 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -37,11 +37,10 @@ let globalId = 0; export function useCharts< TSignatures extends readonly ChartAnyPluginSignature[], - TProps extends Partial>, TSeriesType extends ChartSeriesType, >( inPlugins: ConvertSignaturesIntoPlugins, - props: TProps, + props: Partial>, seriesConfig: ChartSeriesConfig, ) { type TSignaturesWithCorePluginSignatures = readonly [ From 14e44e27930d43c87429b38580d6bcb2375cd7f3 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 13:51:42 +0100 Subject: [PATCH 14/32] scripts --- .../src/BarChartPro/BarChartPro.tsx | 67 +++- .../ChartContainerPro/ChartContainerPro.tsx | 310 ++++++++++++++++++ packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 34 +- .../src/LineChartPro/LineChartPro.tsx | 89 ++++- .../src/ScatterChartPro/ScatterChartPro.tsx | 50 ++- packages/x-charts/src/BarChart/BarChart.tsx | 8 + .../src/ChartContainer/ChartContainer.tsx | 270 +++++++++++++++ packages/x-charts/src/LineChart/LineChart.tsx | 24 ++ packages/x-charts/src/PieChart/PieChart.tsx | 24 ++ .../src/ScatterChart/ScatterChart.tsx | 24 ++ .../src/SparkLineChart/SparkLineChart.tsx | 24 ++ .../ChartDataProvider/ChartDataProvider.tsx | 1 + 12 files changed, 917 insertions(+), 8 deletions(-) diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 5931053b49d9..5e3194c38d36 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -240,6 +240,12 @@ BarChartPro.propTypes = { * @param {BarItemIdentifier} barItemIdentifier The bar item identifier. */ onItemClick: PropTypes.func, + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -251,6 +257,14 @@ BarChartPro.propTypes = { * An array of [[BarSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. @@ -357,7 +371,7 @@ BarChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -443,7 +457,7 @@ BarChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -455,6 +469,55 @@ BarChartPro.propTypes = { ]), }), ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), + /** + * The list of zoom data related to each axis. + */ + zoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), } as any; export { BarChartPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 94994b0bb871..72258f1c7b7b 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import type {} from '../typeOverloads'; import { Watermark } from '@mui/x-license/Watermark'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; @@ -63,4 +64,313 @@ const ChartContainerPro = React.forwardRef(function ChartContainerProInner< props: ChartContainerProProps & { ref?: React.ForwardedRef }, ) => React.JSX.Element; +ChartContainerPro.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "pnpm proptypes" | + // ---------------------------------------------------------------------- + children: PropTypes.node, + className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), + /** + * An array of objects that can be used to populate series and axes data using their `dataKey` property. + */ + dataset: PropTypes.arrayOf(PropTypes.object), + desc: PropTypes.string, + /** + * If `true`, the charts will not listen to the mouse move event. + * It might break interactive features, but will improve performance. + * @default false + */ + disableAxisListener: PropTypes.bool, + /** + * The height of the chart in px. If not defined, it takes the height of the parent element. + */ + height: PropTypes.number, + /** + * The item currently highlighted. Turns highlighting into a controlled prop. + */ + highlightedItem: PropTypes.shape({ + dataIndex: PropTypes.number, + seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, + /** + * The margin between the SVG and the drawing area. + * It's used for leaving some space for extra information such as the x- and y-axis or legend. + * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. + */ + margin: PropTypes.shape({ + bottom: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + }), + /** + * The callback fired when the highlighted item changes. + * + * @param {HighlightItemData | null} highlightedItem The newly highlighted item. + */ + onHighlightChange: PropTypes.func, + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange: PropTypes.func, + plugins: PropTypes.arrayOf(PropTypes.func.isRequired), + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series: PropTypes.arrayOf(PropTypes.object), + seriesConfig: PropTypes.object, + /** + * If `true`, animations are skipped. + * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. + */ + skipAnimation: PropTypes.bool, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + theme: PropTypes.oneOf(['dark', 'light']), + title: PropTypes.string, + /** + * The width of the chart in px. If not defined, it takes the width of the parent element. + */ + width: PropTypes.number, + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['bottom', 'top']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + zoom: PropTypes.oneOfType([ + PropTypes.shape({ + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, + maxEnd: PropTypes.number, + maxSpan: PropTypes.number, + minSpan: PropTypes.number, + minStart: PropTypes.number, + panning: PropTypes.bool, + step: PropTypes.number, + }), + PropTypes.bool, + ]), + }), + ), + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['left', 'right']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + zoom: PropTypes.oneOfType([ + PropTypes.shape({ + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, + maxEnd: PropTypes.number, + maxSpan: PropTypes.number, + minSpan: PropTypes.number, + minStart: PropTypes.number, + panning: PropTypes.bool, + step: PropTypes.number, + }), + PropTypes.bool, + ]), + }), + ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), + /** + * The list of zoom data related to each axis. + */ + zoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), +} as any; + export { ChartContainerPro }; diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index 0adbe0be250c..f071998b1d29 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -296,6 +296,36 @@ Heatmap.propTypes = { * An array of [[HeatmapSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + heatmap: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * The props used for each component slot. * @default {} @@ -404,7 +434,7 @@ Heatmap.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -492,7 +522,7 @@ Heatmap.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index ed2086784e81..8a2b6c751818 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -312,6 +312,12 @@ LineChartPro.propTypes = { * Callback fired when a mark element is clicked. */ onMarkClick: PropTypes.func, + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -323,6 +329,36 @@ LineChartPro.propTypes = { * An array of [[LineSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + heatmap: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * @default false @@ -429,7 +465,7 @@ LineChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -515,7 +551,7 @@ LineChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -527,6 +563,55 @@ LineChartPro.propTypes = { ]), }), ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), + /** + * The list of zoom data related to each axis. + */ + zoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), } as any; export { LineChartPro }; diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index d780e91be85c..d6024f3f36f6 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -173,6 +173,12 @@ ScatterChartPro.propTypes = { * @param {ScatterItemIdentifier} scatterItemIdentifier The scatter item identifier. */ onItemClick: PropTypes.func, + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange: PropTypes.func, /** * Indicate which axis to display the right of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -184,6 +190,36 @@ ScatterChartPro.propTypes = { * An array of [[ScatterSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + heatmap: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. @@ -295,7 +331,7 @@ ScatterChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -381,7 +417,7 @@ ScatterChartPro.propTypes = { valueFormatter: PropTypes.func, zoom: PropTypes.oneOfType([ PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'empty', 'keep']).isRequired, + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, maxEnd: PropTypes.number, maxSpan: PropTypes.number, minSpan: PropTypes.number, @@ -432,6 +468,16 @@ ScatterChartPro.propTypes = { min: PropTypes.number, }), ), + /** + * The list of zoom data related to each axis. + */ + zoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), } as any; export { ScatterChartPro }; diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index d42550a7ff06..9e925a99f50a 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -268,6 +268,14 @@ BarChart.propTypes = { * An array of [[BarSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 3656d66e6780..9c293438cb9c 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { ChartSeriesType } from '../models/seriesType/config'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; import { useChartContainerProps } from './useChartContainerProps'; @@ -55,4 +56,273 @@ const ChartContainer = React.forwardRef(function ChartContainer & { ref?: React.ForwardedRef }, ) => React.JSX.Element; +ChartContainer.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "pnpm proptypes" | + // ---------------------------------------------------------------------- + children: PropTypes.node, + className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), + /** + * An array of objects that can be used to populate series and axes data using their `dataKey` property. + */ + dataset: PropTypes.arrayOf(PropTypes.object), + desc: PropTypes.string, + /** + * If `true`, the charts will not listen to the mouse move event. + * It might break interactive features, but will improve performance. + * @default false + */ + disableAxisListener: PropTypes.bool, + /** + * The height of the chart in px. If not defined, it takes the height of the parent element. + */ + height: PropTypes.number, + /** + * The item currently highlighted. Turns highlighting into a controlled prop. + */ + highlightedItem: PropTypes.shape({ + dataIndex: PropTypes.number, + seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, + /** + * The margin between the SVG and the drawing area. + * It's used for leaving some space for extra information such as the x- and y-axis or legend. + * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. + */ + margin: PropTypes.shape({ + bottom: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + }), + /** + * The callback fired when the highlighted item changes. + * + * @param {HighlightItemData | null} highlightedItem The newly highlighted item. + */ + onHighlightChange: PropTypes.func, + plugins: PropTypes.arrayOf(PropTypes.func.isRequired), + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series: PropTypes.arrayOf(PropTypes.object), + seriesConfig: PropTypes.object, + /** + * If `true`, animations are skipped. + * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. + */ + skipAnimation: PropTypes.bool, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + theme: PropTypes.oneOf(['dark', 'light']), + title: PropTypes.string, + /** + * The width of the chart in px. If not defined, it takes the width of the parent element. + */ + width: PropTypes.number, + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['bottom', 'top']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + }), + ), + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['left', 'right']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + }), + ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), +} as any; + export { ChartContainer }; diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 9f1ddbd4ffb7..bb1e95531a99 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -302,6 +302,30 @@ LineChart.propTypes = { * An array of [[LineSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * @default false diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index ecf9f2f3cacc..de08de9f78a9 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -209,6 +209,30 @@ PieChart.propTypes = { * An array of [[PieSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index 4b5cd53b9358..a8c5f1a082ed 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -257,6 +257,30 @@ ScatterChart.propTypes = { * An array of [[ScatterSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 333b81003bc0..31cba06113c1 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -318,6 +318,30 @@ SparkLineChart.propTypes = { * @default 'line' */ plotType: PropTypes.oneOf(['bar', 'line']), + seriesConfig: PropTypes.shape({ + bar: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + line: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + pie: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + }).isRequired, + scatter: PropTypes.shape({ + colorProcessor: PropTypes.func.isRequired, + seriesProcessor: PropTypes.func.isRequired, + xExtremumGetter: PropTypes.func.isRequired, + yExtremumGetter: PropTypes.func.isRequired, + }).isRequired, + }), /** * Set to `true` to highlight the value. * With line, it shows a point. diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 73f7d34e77e2..7f90dfee1265 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -125,6 +125,7 @@ ChartDataProvider.propTypes = { * Please refer to the appropriate docs page to learn more about it. */ series: PropTypes.any, + seriesConfig: PropTypes.object, /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. From e2f138f40e8cb86ec66ede0a58fd17105abf1906 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 16:28:24 +0100 Subject: [PATCH 15/32] Try zoom feature --- .../src/context/ZoomProvider/useSetupZoom.ts | 383 ------------------ .../useChartProZoom.selectors.ts | 10 + .../useChartProZoom/useChartProZoom.ts | 251 +++++++++++- .../useChartProZoom/useChartProZoom.types.ts | 2 +- .../useChartProZoom/useChartProZoom.utils.ts | 162 +++++++- .../useChartCartesianAxis.selectors.ts | 16 +- .../useChartCartesianAxis.types.ts | 15 +- .../src/internals/plugins/models/plugin.ts | 1 + .../src/internals/store/useChartModels.ts | 3 +- 9 files changed, 424 insertions(+), 419 deletions(-) delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts deleted file mode 100644 index 668b8e4b4515..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupZoom.ts +++ /dev/null @@ -1,383 +0,0 @@ -'use client'; -import * as React from 'react'; -import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { - AxisId, - ChartSeriesType, - DefaultizedZoomOption, - getSVGPoint, - UseChartCartesianAxisSignature, - useChartContext, - useSelector, - useStore, - ZoomData, -} from '@mui/x-charts/internals'; -import { UseChartProZoomSignature } from '../../internals/plugins/useChartProZoom/useChartProZoom.types'; -import { selectorChartZoomOptions } from '../../internals/plugins/useChartProZoom'; - -/** - * Helper to get the range (in percents of a reference range) corresponding to a given scale. - * @param centerRatio {number} The ratio of the point that should not move between the previous and next range. - * @param scaleRatio {number} The target scale ratio. - * @returns The range to display. - */ -const zoomAtPoint = ( - centerRatio: number, - scaleRatio: number, - currentZoomData: ZoomData, - options: DefaultizedZoomOption, -) => { - const MIN_RANGE = options.minStart; - const MAX_RANGE = options.maxEnd; - - const MIN_ALLOWED_SPAN = options.minSpan; - - const minRange = currentZoomData.start; - const maxRange = currentZoomData.end; - - const point = minRange + centerRatio * (maxRange - minRange); - - let newMinRange = (minRange + point * (scaleRatio - 1)) / scaleRatio; - let newMaxRange = (maxRange + point * (scaleRatio - 1)) / scaleRatio; - - let minSpillover = 0; - let maxSpillover = 0; - - if (newMinRange < MIN_RANGE) { - minSpillover = Math.abs(newMinRange); - newMinRange = MIN_RANGE; - } - if (newMaxRange > MAX_RANGE) { - maxSpillover = Math.abs(newMaxRange - MAX_RANGE); - newMaxRange = MAX_RANGE; - } - - if (minSpillover > 0 && maxSpillover > 0) { - return [MIN_RANGE, MAX_RANGE]; - } - - newMaxRange += minSpillover; - newMinRange -= maxSpillover; - - newMinRange = Math.min(MAX_RANGE - MIN_ALLOWED_SPAN, Math.max(MIN_RANGE, newMinRange)); - newMaxRange = Math.max(MIN_ALLOWED_SPAN, Math.min(MAX_RANGE, newMaxRange)); - - return [newMinRange, newMaxRange]; -}; - -export const useSetupZoom = () => { - const store = useStore<[UseChartCartesianAxisSignature, UseChartProZoomSignature]>(); - - const options = useSelector(store, selectorChartZoomOptions); - const isZoomEnabled = Object.keys(options).length > 0; - const setZoomMap = React.useCallback( - (updateFunction: (zoomMap: Map) => Map) => - store.update((prev) => ({ - ...prev, - zoom: { - ...prev.zoom, - zoomMap: updateFunction(prev.zoom.zoomMap), - }, - })), - [store], - ); - const setIsInteracting = React.useCallback( - (newValue: boolean) => - store.update((prev) => ({ - ...prev, - zoom: { - ...prev.zoom, - isInteracting: newValue, - }, - })), - [store], - ); - - const drawingArea = useDrawingArea(); - const { instance } = useChartContext(); - - const svgRef = useSvgRef(); - const eventCacheRef = React.useRef([]); - const eventPrevDiff = React.useRef(0); - const interactionTimeoutRef = React.useRef(undefined); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null || !isZoomEnabled) { - return () => {}; - } - - const wheelHandler = (event: WheelEvent) => { - if (element === null) { - return; - } - - const point = getSVGPoint(element, event); - - if (!instance.isPointInside(point)) { - return; - } - - event.preventDefault(); - if (interactionTimeoutRef.current) { - clearTimeout(interactionTimeoutRef.current); - } - setIsInteracting(true); - // Debounce transition to `isInteractive=false`. - // Useful because wheel events don't have an "end" event. - interactionTimeoutRef.current = window.setTimeout(() => { - setIsInteracting(false); - }, 166); - - store.update((prevState) => { - const newZoomData = new Map(prevState.zoom.zoomMap); - - let updated = false; - newZoomData.forEach((zoom, key) => { - const option = options[zoom.axisId]; - if (!option) { - return; - } - - const centerRatio = - option.axisDirection === 'x' - ? getHorizontalCenterRatio(point, drawingArea) - : getVerticalCenterRatio(point, drawingArea); - - const { scaleRatio, isZoomIn } = getWheelScaleRatio(event, option.step); - const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); - - if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { - return; - } - - updated = true; - - newZoomData.set(key, { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }); - }); - - return updated - ? { - ...prevState, - zoom: { - ...prevState.zoom, - zoomMap: newZoomData, - }, - } - : prevState; - }); - }; - - function pointerDownHandler(event: PointerEvent) { - eventCacheRef.current.push(event); - setIsInteracting(true); - } - - function pointerMoveHandler(event: PointerEvent) { - if (element === null) { - return; - } - - const index = eventCacheRef.current.findIndex( - (cachedEv) => cachedEv.pointerId === event.pointerId, - ); - eventCacheRef.current[index] = event; - - // Not a pinch gesture - if (eventCacheRef.current.length !== 2) { - return; - } - - const firstEvent = eventCacheRef.current[0]; - const curDiff = getDiff(eventCacheRef.current); - - setZoomMap((prevZoomData) => { - const newZoomData = new Map(prevZoomData); - let updated = false; - - prevZoomData.forEach((zoom, key) => { - const option = options[key]; - if (!option) { - return; - } - - const { scaleRatio, isZoomIn } = getPinchScaleRatio( - curDiff, - eventPrevDiff.current, - option.step, - ); - - // If the scale ratio is 0, it means the pinch gesture is not valid. - if (scaleRatio === 0) { - return; - } - - const point = getSVGPoint(element, firstEvent); - - const centerRatio = - option.axisDirection === 'x' - ? getHorizontalCenterRatio(point, drawingArea) - : getVerticalCenterRatio(point, drawingArea); - - const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); - - if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { - return; - } - updated = true; - newZoomData.set(key, { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }); - }); - - eventPrevDiff.current = curDiff; - - return updated ? newZoomData : prevZoomData; - }); - } - - function pointerUpHandler(event: PointerEvent) { - eventCacheRef.current.splice( - eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), - 1, - ); - - if (eventCacheRef.current.length < 2) { - eventPrevDiff.current = 0; - } - - if (event.type === 'pointerup' || event.type === 'pointercancel') { - setIsInteracting(false); - } - } - - element.addEventListener('wheel', wheelHandler); - element.addEventListener('pointerdown', pointerDownHandler); - element.addEventListener('pointermove', pointerMoveHandler); - element.addEventListener('pointerup', pointerUpHandler); - element.addEventListener('pointercancel', pointerUpHandler); - element.addEventListener('pointerout', pointerUpHandler); - element.addEventListener('pointerleave', pointerUpHandler); - - // Prevent zooming the entire page on touch devices - element.addEventListener('touchstart', preventDefault); - element.addEventListener('touchmove', preventDefault); - - return () => { - element.removeEventListener('wheel', wheelHandler); - element.removeEventListener('pointerdown', pointerDownHandler); - element.removeEventListener('pointermove', pointerMoveHandler); - element.removeEventListener('pointerup', pointerUpHandler); - element.removeEventListener('pointercancel', pointerUpHandler); - element.removeEventListener('pointerout', pointerUpHandler); - element.removeEventListener('pointerleave', pointerUpHandler); - element.removeEventListener('touchstart', preventDefault); - element.removeEventListener('touchmove', preventDefault); - if (interactionTimeoutRef.current) { - clearTimeout(interactionTimeoutRef.current); - } - }; - }, [svgRef, drawingArea, isZoomEnabled, options, setIsInteracting, instance, setZoomMap, store]); -}; - -/** - * Checks if the new span is valid. - */ -function isSpanValid( - minRange: number, - maxRange: number, - isZoomIn: boolean, - option: DefaultizedZoomOption, -) { - const newSpanPercent = maxRange - minRange; - - if ( - (isZoomIn && newSpanPercent < option.minSpan) || - (!isZoomIn && newSpanPercent > option.maxSpan) - ) { - return false; - } - - if (minRange < option.minStart || maxRange > option.maxEnd) { - return false; - } - - return true; -} - -function getMultiplier(event: WheelEvent) { - const ctrlMultiplier = event.ctrlKey ? 3 : 1; - - // DeltaMode: 0 is pixel, 1 is line, 2 is page - // This is defined by the browser. - if (event.deltaMode === 1) { - return 1 * ctrlMultiplier; - } - if (event.deltaMode) { - return 10 * ctrlMultiplier; - } - return 0.2 * ctrlMultiplier; -} - -/** - * Get the scale ratio and if it's a zoom in or out from a wheel event. - */ -function getWheelScaleRatio(event: WheelEvent, step: number) { - const deltaY = -event.deltaY; - const multiplier = getMultiplier(event); - const scaledStep = (step * multiplier * deltaY) / 1000; - // Clamp the scale ratio between 0.1 and 1.9 so that the zoom is not too big or too small. - const scaleRatio = Math.min(Math.max(1 + scaledStep, 0.1), 1.9); - const isZoomIn = deltaY > 0; - return { scaleRatio, isZoomIn }; -} - -/** - * Get the scale ratio and if it's a zoom in or out from a pinch gesture. - */ -function getPinchScaleRatio(curDiff: number, prevDiff: number, step: number) { - const scaledStep = step / 1000; - let scaleRatio: number = 0; - let isZoomIn: boolean = false; - - const hasMoved = prevDiff > 0; - - if (hasMoved && curDiff > prevDiff) { - // The distance between the two pointers has increased - scaleRatio = 1 + scaledStep; - isZoomIn = true; - } - if (hasMoved && curDiff < prevDiff) { - // The distance between the two pointers has decreased - scaleRatio = 1 - scaledStep; - isZoomIn = false; - } - - return { scaleRatio, isZoomIn }; -} - -function getDiff(eventCache: PointerEvent[]) { - const [firstEvent, secondEvent] = eventCache; - return Math.hypot(firstEvent.pageX - secondEvent.pageX, firstEvent.pageY - secondEvent.pageY); -} - -/** - * Get the ratio of the point in the horizontal center of the area. - */ -function getHorizontalCenterRatio( - point: { x: number; y: number }, - area: { left: number; width: number }, -) { - const { left, width } = area; - return (point.x - left) / width; -} - -function preventDefault(event: TouchEvent) { - event.preventDefault(); -} - -function getVerticalCenterRatio( - point: { x: number; y: number }, - area: { top: number; height: number }, -) { - const { top, height } = area; - return ((point.y - top) / height) * -1 + 1; -} diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts index 8015beb684b4..35b394692b83 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.selectors.ts @@ -9,7 +9,17 @@ export const selectorChartZoomOptions = createSelector( (zoom) => zoom.options, ); +export const selectorChartZoomData = createSelector( + selectorChartZoomState, + (zoom) => zoom.zoomData, +); + export const selectorChartZoomIsInteracting = createSelector( selectorChartZoomState, (zoom) => zoom.isInteracting, ); + +export const selectorChartZoomIsEnabled = createSelector( + selectorChartZoomOptions, + (options) => Object.keys(options).length > 0, +); diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts index c93abae747f3..023d9b2f4a78 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts @@ -1,9 +1,29 @@ 'use client'; +import * as React from 'react'; +import useControlled from '@mui/utils/useControlled'; import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; -import { ChartPlugin, AxisId, DefaultizedZoomOption } from '@mui/x-charts/internals'; +import { + ChartPlugin, + AxisId, + DefaultizedZoomOption, + useSelector, + getSVGPoint, + selectorChartDrawingArea, + ZoomData, +} from '@mui/x-charts/internals'; import { UseChartProZoomSignature } from './useChartProZoom.types'; import { defaultizeZoom } from './defaultizeZoom'; -import { createZoomMap } from './useChartProZoom.utils'; +import { + getDiff, + getHorizontalCenterRatio, + getPinchScaleRatio, + getVerticalCenterRatio, + getWheelScaleRatio, + isSpanValid, + preventDefault, + zoomAtPoint, +} from './useChartProZoom.utils'; +import { selectorChartZoomOptions } from './useChartProZoom.selectors'; // It is helpful to avoid the need to provide the possibly auto-generated id for each axis. function initializeZoomData(options: Record) { @@ -14,16 +34,223 @@ function initializeZoomData(options: Record) { })); } -export const useChartProZoom: ChartPlugin = ({ store, models }) => { +export const useChartProZoom: ChartPlugin = ({ + store, + // models, + instance, + svgRef, + params, +}) => { + const drawingArea = useSelector(store, selectorChartDrawingArea); + const options = useSelector(store, selectorChartZoomOptions); + const isZoomEnabled = Object.keys(options).length > 0; + + // Add events + const eventCacheRef = React.useRef([]); + const eventPrevDiff = React.useRef(0); + const interactionTimeoutRef = React.useRef(undefined); + + const setIsInteracting = React.useCallback( + (isInteracting: boolean) => { + store.update((prev) => ({ ...prev, zoom: { ...prev.zoom, isInteracting } })); + }, + [store], + ); + + // Default zoom data is initialized only once when uncontrolled. If the user changes the options + // after the initial render, the zoom data will not be updated until the next zoom interaction. + // This is required to avoid warnings about controlled/uncontrolled components. + const defaultZoomData = React.useRef(initializeZoomData(options)); + + const [zoomData, setZoomData] = useControlled({ + controlled: params.zoom, + // eslint-disable-next-line react-compiler/react-compiler + default: defaultZoomData.current, + name: 'ZoomProvider', + state: 'zoom', + }); + useEnhancedEffect(() => { store.update((prevState) => ({ ...prevState, zoom: { ...prevState.zoom, - zoomMap: createZoomMap(models.zoom.value), + zoomData, }, })); - }, [store, models.zoom.value]); + }, [store, zoomData]); + + const setZoomDataCallback = React.useCallback( + (newZoomData) => { + setZoomData(newZoomData); + params.onZoomChange?.(newZoomData); + }, + [setZoomData, params], + ); + + React.useEffect(() => { + const element = svgRef.current; + if (element === null || !isZoomEnabled) { + return () => {}; + } + + const wheelHandler = (event: WheelEvent) => { + if (element === null) { + return; + } + + const point = getSVGPoint(element, event); + + if (!instance.isPointInside(point)) { + return; + } + + event.preventDefault(); + if (interactionTimeoutRef.current) { + clearTimeout(interactionTimeoutRef.current); + } + setIsInteracting(true); + // Debounce transition to `isInteractive=false`. + // Useful because wheel events don't have an "end" event. + interactionTimeoutRef.current = window.setTimeout(() => { + setIsInteracting(false); + }, 166); + + setZoomDataCallback((prevZoomData) => { + return prevZoomData.map((zoom) => { + const option = options[zoom.axisId]; + if (!option) { + return zoom; + } + + const centerRatio = + option.axisDirection === 'x' + ? getHorizontalCenterRatio(point, drawingArea) + : getVerticalCenterRatio(point, drawingArea); + + const { scaleRatio, isZoomIn } = getWheelScaleRatio(event, option.step); + const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); + + if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { + return zoom; + } + + return { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }; + }); + }); + }; + + function pointerDownHandler(event: PointerEvent) { + eventCacheRef.current.push(event); + setIsInteracting(true); + } + + function pointerMoveHandler(event: PointerEvent) { + if (element === null) { + return; + } + + const index = eventCacheRef.current.findIndex( + (cachedEv) => cachedEv.pointerId === event.pointerId, + ); + eventCacheRef.current[index] = event; + + // Not a pinch gesture + if (eventCacheRef.current.length !== 2) { + return; + } + + const firstEvent = eventCacheRef.current[0]; + const curDiff = getDiff(eventCacheRef.current); + + setZoomDataCallback((prevZoomData) => { + const newZoomData = prevZoomData.map((zoom) => { + const option = options[zoom.axisId]; + if (!option) { + return zoom; + } + + const { scaleRatio, isZoomIn } = getPinchScaleRatio( + curDiff, + eventPrevDiff.current, + option.step, + ); + + // If the scale ratio is 0, it means the pinch gesture is not valid. + if (scaleRatio === 0) { + return zoom; + } + + const point = getSVGPoint(element, firstEvent); + + const centerRatio = + option.axisDirection === 'x' + ? getHorizontalCenterRatio(point, drawingArea) + : getVerticalCenterRatio(point, drawingArea); + + const [newMinRange, newMaxRange] = zoomAtPoint(centerRatio, scaleRatio, zoom, option); + + if (!isSpanValid(newMinRange, newMaxRange, isZoomIn, option)) { + return zoom; + } + return { axisId: zoom.axisId, start: newMinRange, end: newMaxRange }; + }); + eventPrevDiff.current = curDiff; + return newZoomData; + }); + } + + function pointerUpHandler(event: PointerEvent) { + eventCacheRef.current.splice( + eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), + 1, + ); + + if (eventCacheRef.current.length < 2) { + eventPrevDiff.current = 0; + } + + if (event.type === 'pointerup' || event.type === 'pointercancel') { + setIsInteracting(false); + } + } + + element.addEventListener('wheel', wheelHandler); + element.addEventListener('pointerdown', pointerDownHandler); + element.addEventListener('pointermove', pointerMoveHandler); + element.addEventListener('pointerup', pointerUpHandler); + element.addEventListener('pointercancel', pointerUpHandler); + element.addEventListener('pointerout', pointerUpHandler); + element.addEventListener('pointerleave', pointerUpHandler); + + // Prevent zooming the entire page on touch devices + element.addEventListener('touchstart', preventDefault); + element.addEventListener('touchmove', preventDefault); + + return () => { + element.removeEventListener('wheel', wheelHandler); + element.removeEventListener('pointerdown', pointerDownHandler); + element.removeEventListener('pointermove', pointerMoveHandler); + element.removeEventListener('pointerup', pointerUpHandler); + element.removeEventListener('pointercancel', pointerUpHandler); + element.removeEventListener('pointerout', pointerUpHandler); + element.removeEventListener('pointerleave', pointerUpHandler); + element.removeEventListener('touchstart', preventDefault); + element.removeEventListener('touchmove', preventDefault); + if (interactionTimeoutRef.current) { + clearTimeout(interactionTimeoutRef.current); + } + }; + }, [ + svgRef, + setZoomData, + drawingArea, + isZoomEnabled, + options, + setIsInteracting, + instance, + setZoomDataCallback, + ]); return {}; }; @@ -59,19 +286,17 @@ useChartProZoom.getDefaultizedParams = ({ params }) => { }; }; -useChartProZoom.models = { - zoom: { - getDefaultValue: (params) => initializeZoomData(params.options), - }, -}; +// useChartProZoom.models = { +// zoom: { +// getDefaultValue: (params) => initializeZoomData(params.options), +// }, +// }; useChartProZoom.getInitialState = (params) => { return { zoom: { options: params.options, - zoomMap: createZoomMap( - params.zoom === undefined ? initializeZoomData(params.options) : params.zoom, - ), + zoomData: params.zoom === undefined ? initializeZoomData(params.options) : params.zoom, isInteracting: false, }, }; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts index 6cd3c2e69bbe..afc4091a2d66 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts @@ -43,7 +43,7 @@ export interface UseChartProZoomState { /** * Mapping of axis id to the zoom data. */ - zoomMap: Map; + zoomData: ZoomData[]; }; } diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts index 869c37d8e5f8..705ad86470db 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.utils.ts @@ -1,9 +1,155 @@ -import { AxisId, ZoomData } from '@mui/x-charts/internals'; - -export const createZoomMap = (zoom: ZoomData[]) => { - const selectedItemsMap = new Map(); - zoom.forEach((zoomItem) => { - selectedItemsMap.set(zoomItem.axisId, zoomItem); - }); - return selectedItemsMap; +import { DefaultizedZoomOption, ZoomData } from '@mui/x-charts/internals'; + +/** + * Helper to get the range (in percents of a reference range) corresponding to a given scale. + * @param centerRatio {number} The ratio of the point that should not move between the previous and next range. + * @param scaleRatio {number} The target scale ratio. + * @returns The range to display. + */ +export const zoomAtPoint = ( + centerRatio: number, + scaleRatio: number, + currentZoomData: ZoomData, + options: DefaultizedZoomOption, +) => { + const MIN_RANGE = options.minStart; + const MAX_RANGE = options.maxEnd; + + const MIN_ALLOWED_SPAN = options.minSpan; + + const minRange = currentZoomData.start; + const maxRange = currentZoomData.end; + + const point = minRange + centerRatio * (maxRange - minRange); + + let newMinRange = (minRange + point * (scaleRatio - 1)) / scaleRatio; + let newMaxRange = (maxRange + point * (scaleRatio - 1)) / scaleRatio; + + let minSpillover = 0; + let maxSpillover = 0; + + if (newMinRange < MIN_RANGE) { + minSpillover = Math.abs(newMinRange); + newMinRange = MIN_RANGE; + } + if (newMaxRange > MAX_RANGE) { + maxSpillover = Math.abs(newMaxRange - MAX_RANGE); + newMaxRange = MAX_RANGE; + } + + if (minSpillover > 0 && maxSpillover > 0) { + return [MIN_RANGE, MAX_RANGE]; + } + + newMaxRange += minSpillover; + newMinRange -= maxSpillover; + + newMinRange = Math.min(MAX_RANGE - MIN_ALLOWED_SPAN, Math.max(MIN_RANGE, newMinRange)); + newMaxRange = Math.max(MIN_ALLOWED_SPAN, Math.min(MAX_RANGE, newMaxRange)); + + return [newMinRange, newMaxRange]; }; + +/** + * Checks if the new span is valid. + */ +export function isSpanValid( + minRange: number, + maxRange: number, + isZoomIn: boolean, + option: DefaultizedZoomOption, +) { + const newSpanPercent = maxRange - minRange; + + if ( + (isZoomIn && newSpanPercent < option.minSpan) || + (!isZoomIn && newSpanPercent > option.maxSpan) + ) { + return false; + } + + if (minRange < option.minStart || maxRange > option.maxEnd) { + return false; + } + + return true; +} + +function getMultiplier(event: WheelEvent) { + const ctrlMultiplier = event.ctrlKey ? 3 : 1; + + // DeltaMode: 0 is pixel, 1 is line, 2 is page + // This is defined by the browser. + if (event.deltaMode === 1) { + return 1 * ctrlMultiplier; + } + if (event.deltaMode) { + return 10 * ctrlMultiplier; + } + return 0.2 * ctrlMultiplier; +} + +/** + * Get the scale ratio and if it's a zoom in or out from a wheel event. + */ +export function getWheelScaleRatio(event: WheelEvent, step: number) { + const deltaY = -event.deltaY; + const multiplier = getMultiplier(event); + const scaledStep = (step * multiplier * deltaY) / 1000; + // Clamp the scale ratio between 0.1 and 1.9 so that the zoom is not too big or too small. + const scaleRatio = Math.min(Math.max(1 + scaledStep, 0.1), 1.9); + const isZoomIn = deltaY > 0; + return { scaleRatio, isZoomIn }; +} + +/** + * Get the scale ratio and if it's a zoom in or out from a pinch gesture. + */ +export function getPinchScaleRatio(curDiff: number, prevDiff: number, step: number) { + const scaledStep = step / 1000; + let scaleRatio: number = 0; + let isZoomIn: boolean = false; + + const hasMoved = prevDiff > 0; + + if (hasMoved && curDiff > prevDiff) { + // The distance between the two pointers has increased + scaleRatio = 1 + scaledStep; + isZoomIn = true; + } + if (hasMoved && curDiff < prevDiff) { + // The distance between the two pointers has decreased + scaleRatio = 1 - scaledStep; + isZoomIn = false; + } + + return { scaleRatio, isZoomIn }; +} + +export function getDiff(eventCache: PointerEvent[]) { + const [firstEvent, secondEvent] = eventCache; + return Math.hypot(firstEvent.pageX - secondEvent.pageX, firstEvent.pageY - secondEvent.pageY); +} + +/** + * Get the ratio of the point in the horizontal center of the area. + */ +export function getHorizontalCenterRatio( + point: { x: number; y: number }, + area: { left: number; width: number }, +) { + const { left, width } = area; + return (point.x - left) / width; +} + +export function preventDefault(event: TouchEvent) { + event.preventDefault(); +} + +export function getVerticalCenterRatio( + point: { x: number; y: number }, + area: { top: number; height: number }, +) { + const { top, height } = area; + return ((point.y - top) / height) * -1 + 1; +} diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts index 6981209d2c27..0196bc0a1cc1 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts @@ -3,12 +3,21 @@ import { selectorChartSeriesConfig, selectorChartSeriesProcessed, } from '../../corePlugins/useChartSeries'; +import { AxisId } from '../../../../models/axis'; import { createSelector } from '../../utils/selectors'; import { computeAxisValue } from './computeAxisValue'; import { UseChartCartesianAxisSignature } from './useChartCartesianAxis.types'; import { ChartState } from '../../models/chart'; import { createAxisFilterMapper, createGetAxisFilters } from './createAxisFilterMapper'; -import { ZoomAxisFilters } from './zoom.types'; +import { ZoomAxisFilters, ZoomData } from './zoom.types'; + +export const createZoomMap = (zoom: ZoomData[]) => { + const zoomItemMap = new Map(); + zoom.forEach((zoomItem) => { + zoomItemMap.set(zoomItem.axisId, zoomItem); + }); + return zoomItemMap; +}; export const selectorChartCartesianAxisState = ( state: ChartState<[UseChartCartesianAxisSignature]>, @@ -30,7 +39,10 @@ export const selectorChartRawYAxis = createSelector( * Following selectors are not exported because they exist in the MIT chart only to ba able to reuse the Zoom state from the pro. */ -const selectorChartZoomMap = createSelector(selectorChartZoomState, (zoom) => zoom?.zoomMap); +const selectorChartZoomMap = createSelector( + selectorChartZoomState, + (zoom) => zoom?.zoomData && createZoomMap(zoom?.zoomData), +); const selectorChartZoomOptions = createSelector(selectorChartZoomState, (zoom) => zoom?.options); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts index 3a4c8abcc1e8..781f5159cb03 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.types.ts @@ -62,20 +62,13 @@ export interface DefaultizedZoomOption extends Required { } export interface UseChartCartesianAxisState { + /** + * @ignore - state populated by the useChartProZoomPlugin + */ zoom?: { - /** - * The zoom options for each axis. - */ options: Record; - /** - * Whether the user is currently interacting with the chart. - * This is useful to prevent animations from running while the user is interacting. - */ isInteracting: boolean; - /** - * Mapping of axis id to the zoom data. - */ - zoomMap: Map; + zoomData: ZoomData[]; }; cartesianAxis: { x: AxisConfig[]; diff --git a/packages/x-charts/src/internals/plugins/models/plugin.ts b/packages/x-charts/src/internals/plugins/models/plugin.ts index caf391396c24..4d38557d8b4c 100644 --- a/packages/x-charts/src/internals/plugins/models/plugin.ts +++ b/packages/x-charts/src/internals/plugins/models/plugin.ts @@ -102,6 +102,7 @@ export interface ChartControlModel { name: string; value: TValue; setControlledValue: (value: TValue | ((prevValue: TValue) => TValue)) => void; + isControlled: boolean; } type RemoveSetValue>> = { diff --git a/packages/x-charts/src/internals/store/useChartModels.ts b/packages/x-charts/src/internals/store/useChartModels.ts index 532e5e709d7a..a8c915892d72 100644 --- a/packages/x-charts/src/internals/store/useChartModels.ts +++ b/packages/x-charts/src/internals/store/useChartModels.ts @@ -54,10 +54,11 @@ export const useChartModels = ({ ...prevState, - [modelName]: newValue, + [modelName]: typeof newValue === 'function' ? newValue(value) : newValue, })); } }, + isControlled: modelsRef.current[modelName].isControlled, }, ]; }), From 1d171086cfd44063a2539eef9a679ddd0e2021ca Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 18:19:44 +0100 Subject: [PATCH 16/32] all empty axes --- packages/x-charts/src/Gauge/GaugeContainer.tsx | 3 +-- packages/x-charts/src/hooks/useAxis.ts | 2 +- packages/x-charts/src/hooks/useAxisEvents.ts | 2 +- .../corePlugins/useChartId/useChartId.types.ts | 2 +- .../useChartCartesianAxis/computeAxisValue.ts | 13 ++++++++++--- .../useChartCartesianAxis.selectors.ts | 4 ++-- packages/x-charts/src/internals/store/useStore.ts | 14 +++----------- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index f07cd3da3428..ca1f16dcff16 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -52,8 +52,8 @@ const GaugeContainer = React.forwardRef(function GaugeContainer( width: inWidth, height: inHeight, margin: { left: 10, right: 10, top: 10, bottom: 10, ...margin }, - series: [], }} + plugins={[]} > { const { xAxis, xAxisIds } = useXAxes(); const { yAxis, yAxisIds } = useYAxes(); - const store = useStore(disableAxisListener); + const store = useStore(); const usedXAxis = xAxisIds[0]; const usedYAxis = yAxisIds[0]; diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts index e57df61977e9..64022b92517c 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartId/useChartId.types.ts @@ -5,7 +5,7 @@ export interface UseChartIdParameters { * This prop is used to help implement the accessibility logic. * If you don't provide this prop. It falls back to a randomly generated id. */ - id: string | undefined; + id?: string | undefined; } export type UseChartIdDefaultizedParameters = Required; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts index a6f6cd9c489d..70c2ead6bedd 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts @@ -64,13 +64,13 @@ type ComputeCommonParams = { export function computeAxisValue( options: ComputeCommonParams & { - axis: AxisConfig[]; + axis?: AxisConfig[]; axisDirection: 'y'; }, ): ComputeResult; export function computeAxisValue( options: ComputeCommonParams & { - axis: AxisConfig[]; + axis?: AxisConfig[]; axisDirection: 'x'; }, ): ComputeResult; @@ -84,9 +84,16 @@ export function computeAxisValue({ zoomOptions, getFilters, }: ComputeCommonParams & { - axis: AxisConfig[]; + axis?: AxisConfig[]; axisDirection: 'x' | 'y'; // | 'radius' | 'rotation'; }) { + if (allAxis === undefined) { + return { + axis: {}, + axisIds: [], + }; + } + const completeAxis: DefaultizedAxisConfig = {}; allAxis.forEach((eachAxis, axisIndex) => { const axis = eachAxis as Readonly>>; diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts index 0196bc0a1cc1..75182121563f 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/useChartCartesianAxis.selectors.ts @@ -27,12 +27,12 @@ const selectorChartZoomState = (state: ChartState<[UseChartCartesianAxisSignatur export const selectorChartRawXAxis = createSelector( selectorChartCartesianAxisState, - (axis) => axis.x, + (axis) => axis?.x, ); export const selectorChartRawYAxis = createSelector( selectorChartCartesianAxisState, - (axis) => axis.y, + (axis) => axis?.y, ); /** diff --git a/packages/x-charts/src/internals/store/useStore.ts b/packages/x-charts/src/internals/store/useStore.ts index eb9f0cc3fd22..9a82698b4b2c 100644 --- a/packages/x-charts/src/internals/store/useStore.ts +++ b/packages/x-charts/src/internals/store/useStore.ts @@ -4,19 +4,11 @@ import { UseChartInteractionSignature } from '../plugins/featurePlugins/useChart import { ChartAnyPluginSignature } from '../plugins/models'; // This hook should be removed because user and us should not interact with the store directly, but with public/private APIs -export function useStore( - skipError?: boolean, -): ChartStore<[...TSignatures, UseChartInteractionSignature]> { +export function useStore(): ChartStore< + [...TSignatures, UseChartInteractionSignature] +> { const context = useChartContext(); - if (skipError) { - // TODO: Remove once store is used by all charts. - // This line is only for `useAxisEvents` which is in the surface of the Gauge. - // But the Gauge don't have store yet because it does not need the interaction provider. - // Will be fixed when every thing move to the store since every component will have access to it. - // @ts-ignore - return context?.store; - } if (!context) { throw new Error( [ From d17f1730785120f3911f3e290c2b0595eee44cc3 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 12 Dec 2024 18:28:31 +0100 Subject: [PATCH 17/32] remove-proptypes --- docs/scripts/generateProptypes.ts | 2 +- .../ChartContainerPro/ChartContainerPro.tsx | 309 ------------------ .../src/ChartContainer/ChartContainer.tsx | 270 --------------- 3 files changed, 1 insertion(+), 580 deletions(-) diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index 832fb60f8047..3e1c482cefba 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -10,7 +10,7 @@ import { import { fixBabelGeneratorIssues, fixLineEndings } from '@mui/internal-docs-utils'; import { createXTypeScriptProjects, XTypeScriptProject } from './createXTypeScriptProjects'; -const COMPONENTS_WITHOUT_PROPTYPES = ['AnimatedBarElement']; +const COMPONENTS_WITHOUT_PROPTYPES = ['AnimatedBarElement', 'ChartContainer', 'ChartContainerPro']; async function generateProptypes(project: XTypeScriptProject, sourceFile: string) { const isDateObject = (name: string) => { diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 72258f1c7b7b..52bd26f3b82d 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -64,313 +64,4 @@ const ChartContainerPro = React.forwardRef(function ChartContainerProInner< props: ChartContainerProProps & { ref?: React.ForwardedRef }, ) => React.JSX.Element; -ChartContainerPro.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - children: PropTypes.node, - className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset: PropTypes.arrayOf(PropTypes.object), - desc: PropTypes.string, - /** - * If `true`, the charts will not listen to the mouse move event. - * It might break interactive features, but will improve performance. - * @default false - */ - disableAxisListener: PropTypes.bool, - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height: PropTypes.number, - /** - * The item currently highlighted. Turns highlighting into a controlled prop. - */ - highlightedItem: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - }), - /** - * This prop is used to help implement the accessibility logic. - * If you don't provide this prop. It falls back to a randomly generated id. - */ - id: PropTypes.string, - /** - * The margin between the SVG and the drawing area. - * It's used for leaving some space for extra information such as the x- and y-axis or legend. - * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - */ - margin: PropTypes.shape({ - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - top: PropTypes.number, - }), - /** - * The callback fired when the highlighted item changes. - * - * @param {HighlightItemData | null} highlightedItem The newly highlighted item. - */ - onHighlightChange: PropTypes.func, - /** - * Callback fired when the zoom has changed. - * - * @param {ZoomData[]} zoomData Updated zoom data. - */ - onZoomChange: PropTypes.func, - plugins: PropTypes.arrayOf(PropTypes.func.isRequired), - /** - * The array of series to display. - * Each type of series has its own specificity. - * Please refer to the appropriate docs page to learn more about it. - */ - series: PropTypes.arrayOf(PropTypes.object), - seriesConfig: PropTypes.object, - /** - * If `true`, animations are skipped. - * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. - */ - skipAnimation: PropTypes.bool, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - theme: PropTypes.oneOf(['dark', 'light']), - title: PropTypes.string, - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - zoom: PropTypes.oneOfType([ - PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, - maxEnd: PropTypes.number, - maxSpan: PropTypes.number, - minSpan: PropTypes.number, - minStart: PropTypes.number, - panning: PropTypes.bool, - step: PropTypes.number, - }), - PropTypes.bool, - ]), - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - zoom: PropTypes.oneOfType([ - PropTypes.shape({ - filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, - maxEnd: PropTypes.number, - maxSpan: PropTypes.number, - minSpan: PropTypes.number, - minStart: PropTypes.number, - panning: PropTypes.bool, - step: PropTypes.number, - }), - PropTypes.bool, - ]), - }), - ), - /** - * The configuration of the z-axes. - */ - zAxis: PropTypes.arrayOf( - PropTypes.shape({ - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - id: PropTypes.string, - max: PropTypes.number, - min: PropTypes.number, - }), - ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), -} as any; - export { ChartContainerPro }; diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 9c293438cb9c..3656d66e6780 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -1,6 +1,5 @@ 'use client'; import * as React from 'react'; -import PropTypes from 'prop-types'; import { ChartSeriesType } from '../models/seriesType/config'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; import { useChartContainerProps } from './useChartContainerProps'; @@ -56,273 +55,4 @@ const ChartContainer = React.forwardRef(function ChartContainer & { ref?: React.ForwardedRef }, ) => React.JSX.Element; -ChartContainer.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - children: PropTypes.node, - className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), - /** - * An array of objects that can be used to populate series and axes data using their `dataKey` property. - */ - dataset: PropTypes.arrayOf(PropTypes.object), - desc: PropTypes.string, - /** - * If `true`, the charts will not listen to the mouse move event. - * It might break interactive features, but will improve performance. - * @default false - */ - disableAxisListener: PropTypes.bool, - /** - * The height of the chart in px. If not defined, it takes the height of the parent element. - */ - height: PropTypes.number, - /** - * The item currently highlighted. Turns highlighting into a controlled prop. - */ - highlightedItem: PropTypes.shape({ - dataIndex: PropTypes.number, - seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - }), - /** - * This prop is used to help implement the accessibility logic. - * If you don't provide this prop. It falls back to a randomly generated id. - */ - id: PropTypes.string, - /** - * The margin between the SVG and the drawing area. - * It's used for leaving some space for extra information such as the x- and y-axis or legend. - * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. - */ - margin: PropTypes.shape({ - bottom: PropTypes.number, - left: PropTypes.number, - right: PropTypes.number, - top: PropTypes.number, - }), - /** - * The callback fired when the highlighted item changes. - * - * @param {HighlightItemData | null} highlightedItem The newly highlighted item. - */ - onHighlightChange: PropTypes.func, - plugins: PropTypes.arrayOf(PropTypes.func.isRequired), - /** - * The array of series to display. - * Each type of series has its own specificity. - * Please refer to the appropriate docs page to learn more about it. - */ - series: PropTypes.arrayOf(PropTypes.object), - seriesConfig: PropTypes.object, - /** - * If `true`, animations are skipped. - * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. - */ - skipAnimation: PropTypes.bool, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - theme: PropTypes.oneOf(['dark', 'light']), - title: PropTypes.string, - /** - * The width of the chart in px. If not defined, it takes the width of the parent element. - */ - width: PropTypes.number, - /** - * The configuration of the x-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - xAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['bottom', 'top']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the y-axes. - * If not provided, a default axis config is used. - * An array of [[AxisConfig]] objects. - */ - yAxis: PropTypes.arrayOf( - PropTypes.shape({ - classes: PropTypes.object, - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - disableLine: PropTypes.bool, - disableTicks: PropTypes.bool, - domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), - fill: PropTypes.string, - hideTooltip: PropTypes.bool, - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - label: PropTypes.string, - labelStyle: PropTypes.object, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - position: PropTypes.oneOf(['left', 'right']), - reverse: PropTypes.bool, - scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), - slotProps: PropTypes.object, - slots: PropTypes.object, - stroke: PropTypes.string, - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), - tickInterval: PropTypes.oneOfType([ - PropTypes.oneOf(['auto']), - PropTypes.array, - PropTypes.func, - ]), - tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), - tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), - tickLabelStyle: PropTypes.object, - tickMaxStep: PropTypes.number, - tickMinStep: PropTypes.number, - tickNumber: PropTypes.number, - tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), - tickSize: PropTypes.number, - valueFormatter: PropTypes.func, - }), - ), - /** - * The configuration of the z-axes. - */ - zAxis: PropTypes.arrayOf( - PropTypes.shape({ - colorMap: PropTypes.oneOfType([ - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - type: PropTypes.oneOf(['ordinal']).isRequired, - unknownColor: PropTypes.string, - values: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) - .isRequired, - ), - }), - PropTypes.shape({ - color: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.string.isRequired), - PropTypes.func, - ]).isRequired, - max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), - type: PropTypes.oneOf(['continuous']).isRequired, - }), - PropTypes.shape({ - colors: PropTypes.arrayOf(PropTypes.string).isRequired, - thresholds: PropTypes.arrayOf( - PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, - ).isRequired, - type: PropTypes.oneOf(['piecewise']).isRequired, - }), - ]), - data: PropTypes.array, - dataKey: PropTypes.string, - id: PropTypes.string, - max: PropTypes.number, - min: PropTypes.number, - }), - ), -} as any; - export { ChartContainer }; From 1050ec6f3a130d4788476c119670e53b7918355b Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 16 Dec 2024 16:31:40 +0100 Subject: [PATCH 18/32] Add the zoom panning --- .../src/context/ZoomProvider/useSetupPan.ts | 154 ---------------- .../useChartProZoom/useChartProZoom.ts | 172 ++++++++++++++---- .../useChartProZoom/useChartProZoom.types.ts | 11 +- 3 files changed, 143 insertions(+), 194 deletions(-) delete mode 100644 packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts diff --git a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts b/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts deleted file mode 100644 index b972eda08b24..000000000000 --- a/packages/x-charts-pro/src/context/ZoomProvider/useSetupPan.ts +++ /dev/null @@ -1,154 +0,0 @@ -'use client'; -// import * as React from 'react'; -// import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; - -// import { -// AxisId, -// getSVGPoint, -// useChartContext, -// useSelector, -// useStore, -// } from '@mui/x-charts/internals'; - -// import { ZoomData } from './Zoom.types'; -// import { useZoomIsInteracting } from './useZoom'; -// import { selectorChartZoomOptions } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.selectors'; -// import { UseChartProCartesianAxisSignature } from '../../internals/plugins/useChartProCartesianAxis/useChartProCartesianAxis.types'; - -export const useSetupPan = () => { - // const store = useStore<[UseChartProCartesianAxisSignature]>(); - // const options = useSelector(store, selectorChartZoomOptions); - // const isPanEnabled = options.fo; - // const setZoomMap = React.useCallback( - // (updateFunction: (zoomMap: Map) => Map) => - // store.update((prev) => ({ - // ...prev, - // zoom: { - // ...prev.zoom, - // zoomMap: updateFunction(prev.zoom.zoomMap), - // }, - // })), - // [store], - // ); - // const setIsInteracting = React.useCallback( - // (newValue: boolean) => - // store.update((prev) => ({ - // ...prev, - // zoom: { - // ...prev.zoom, - // isInteracting: newValue, - // }, - // })), - // [store], - // ); - // const drawingArea = useDrawingArea(); - // const { instance } = useChartContext(); - // const svgRef = useSvgRef(); - // const isDraggingRef = React.useRef(false); - // const touchStartRef = React.useRef<{ x: number; y: number; zoomData: ZoomData[] } | null>(null); - // const eventCacheRef = React.useRef([]); - // React.useEffect(() => { - // const element = svgRef.current; - // if (element === null || !isPanEnabled) { - // return () => {}; - // } - // const handlePan = (event: PointerEvent) => { - // if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) { - // return; - // } - // if (touchStartRef.current == null) { - // return; - // } - // const point = getSVGPoint(element, event); - // const movementX = point.x - touchStartRef.current.x; - // const movementY = (point.y - touchStartRef.current.y) * -1; - // const newZoomData = touchStartRef.current.zoomData.map((zoom) => { - // const option = options[zoom.axisId]; - // if (!option || !option.panning) { - // return zoom; - // } - // const min = zoom.start; - // const max = zoom.end; - // const span = max - min; - // const MIN_PERCENT = option.minStart; - // const MAX_PERCENT = option.maxEnd; - // const movement = option.axisDirection === 'x' ? movementX : movementY; - // const dimension = option.axisDirection === 'x' ? drawingArea.width : drawingArea.height; - // let newMinPercent = min - (movement / dimension) * span; - // let newMaxPercent = max - (movement / dimension) * span; - // if (newMinPercent < MIN_PERCENT) { - // newMinPercent = MIN_PERCENT; - // newMaxPercent = newMinPercent + span; - // } - // if (newMaxPercent > MAX_PERCENT) { - // newMaxPercent = MAX_PERCENT; - // newMinPercent = newMaxPercent - span; - // } - // if ( - // newMinPercent < MIN_PERCENT || - // newMaxPercent > MAX_PERCENT || - // span < option.minSpan || - // span > option.maxSpan - // ) { - // return zoom; - // } - // return { - // ...zoom, - // start: newMinPercent, - // end: newMaxPercent, - // }; - // }); - // setZoomData(newZoomData); - // }; - // const handleDown = (event: PointerEvent) => { - // eventCacheRef.current.push(event); - // const point = getSVGPoint(element, event); - // if (!instance.isPointInside(point)) { - // return; - // } - // // If there is only one pointer, prevent selecting text - // if (eventCacheRef.current.length === 1) { - // event.preventDefault(); - // } - // isDraggingRef.current = true; - // setIsInteracting(true); - // touchStartRef.current = { - // x: point.x, - // y: point.y, - // zoomData, - // }; - // }; - // const handleUp = (event: PointerEvent) => { - // eventCacheRef.current.splice( - // eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), - // 1, - // ); - // setIsInteracting(false); - // isDraggingRef.current = false; - // touchStartRef.current = null; - // }; - // element.addEventListener('pointerdown', handleDown); - // document.addEventListener('pointermove', handlePan); - // document.addEventListener('pointerup', handleUp); - // document.addEventListener('pointercancel', handleUp); - // document.addEventListener('pointerleave', handleUp); - // return () => { - // element.removeEventListener('pointerdown', handleDown); - // document.removeEventListener('pointermove', handlePan); - // document.removeEventListener('pointerup', handleUp); - // document.removeEventListener('pointercancel', handleUp); - // document.removeEventListener('pointerleave', handleUp); - // }; - // }, [ - // instance, - // svgRef, - // isDraggingRef, - // setIsInteracting, - // zoomData, - // setZoomData, - // isPanEnabled, - // options, - // drawingArea.width, - // drawingArea.height, - // ]); -}; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts index 023d9b2f4a78..30a2582291ef 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts @@ -1,7 +1,5 @@ 'use client'; import * as React from 'react'; -import useControlled from '@mui/utils/useControlled'; -import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { ChartPlugin, AxisId, @@ -36,7 +34,6 @@ function initializeZoomData(options: Record) { export const useChartProZoom: ChartPlugin = ({ store, - // models, instance, svgRef, params, @@ -57,37 +54,139 @@ export const useChartProZoom: ChartPlugin = ({ [store], ); - // Default zoom data is initialized only once when uncontrolled. If the user changes the options - // after the initial render, the zoom data will not be updated until the next zoom interaction. - // This is required to avoid warnings about controlled/uncontrolled components. - const defaultZoomData = React.useRef(initializeZoomData(options)); - - const [zoomData, setZoomData] = useControlled({ - controlled: params.zoom, - // eslint-disable-next-line react-compiler/react-compiler - default: defaultZoomData.current, - name: 'ZoomProvider', - state: 'zoom', - }); - - useEnhancedEffect(() => { - store.update((prevState) => ({ - ...prevState, - zoom: { - ...prevState.zoom, - zoomData, - }, - })); - }, [store, zoomData]); - const setZoomDataCallback = React.useCallback( - (newZoomData) => { - setZoomData(newZoomData); - params.onZoomChange?.(newZoomData); + (zoomData: ZoomData[] | ((prev: ZoomData[]) => ZoomData[])) => { + store.update((prevState) => { + const newZoomData = + typeof zoomData === 'function' ? zoomData(prevState.zoom.zoomData) : zoomData; + params.onZoomChange?.(newZoomData); + + return { + ...prevState, + zoom: { + ...prevState.zoom, + zoomData: newZoomData, + }, + }; + }); }, - [setZoomData, params], + + [params, store], ); + // Add event for chart panning + const isPanEnabled = React.useMemo( + () => Object.values(options).some((v) => v.panning) || false, + [options], + ); + const isDraggingRef = React.useRef(false); + const touchStartRef = React.useRef<{ x: number; y: number; zoomData: ZoomData[] } | null>(null); + React.useEffect(() => { + const element = svgRef.current; + if (element === null || !isPanEnabled) { + return () => {}; + } + const handlePan = (event: PointerEvent) => { + if (element === null || !isDraggingRef.current || eventCacheRef.current.length > 1) { + return; + } + if (touchStartRef.current == null) { + return; + } + const point = getSVGPoint(element, event); + const movementX = point.x - touchStartRef.current.x; + const movementY = (point.y - touchStartRef.current.y) * -1; + const newZoomData = touchStartRef.current.zoomData.map((zoom) => { + const option = options[zoom.axisId]; + if (!option || !option.panning) { + return zoom; + } + const min = zoom.start; + const max = zoom.end; + const span = max - min; + const MIN_PERCENT = option.minStart; + const MAX_PERCENT = option.maxEnd; + const movement = option.axisDirection === 'x' ? movementX : movementY; + const dimension = option.axisDirection === 'x' ? drawingArea.width : drawingArea.height; + let newMinPercent = min - (movement / dimension) * span; + let newMaxPercent = max - (movement / dimension) * span; + if (newMinPercent < MIN_PERCENT) { + newMinPercent = MIN_PERCENT; + newMaxPercent = newMinPercent + span; + } + if (newMaxPercent > MAX_PERCENT) { + newMaxPercent = MAX_PERCENT; + newMinPercent = newMaxPercent - span; + } + if ( + newMinPercent < MIN_PERCENT || + newMaxPercent > MAX_PERCENT || + span < option.minSpan || + span > option.maxSpan + ) { + return zoom; + } + return { + ...zoom, + start: newMinPercent, + end: newMaxPercent, + }; + }); + setZoomDataCallback(newZoomData); + }; + const handleDown = (event: PointerEvent) => { + eventCacheRef.current.push(event); + const point = getSVGPoint(element, event); + if (!instance.isPointInside(point)) { + return; + } + // If there is only one pointer, prevent selecting text + if (eventCacheRef.current.length === 1) { + event.preventDefault(); + } + isDraggingRef.current = true; + setIsInteracting(true); + touchStartRef.current = { + x: point.x, + y: point.y, + zoomData: store.getSnapshot().zoom.zoomData, + }; + }; + const handleUp = (event: PointerEvent) => { + eventCacheRef.current.splice( + eventCacheRef.current.findIndex((cachedEvent) => cachedEvent.pointerId === event.pointerId), + 1, + ); + setIsInteracting(false); + isDraggingRef.current = false; + touchStartRef.current = null; + }; + element.addEventListener('pointerdown', handleDown); + document.addEventListener('pointermove', handlePan); + document.addEventListener('pointerup', handleUp); + document.addEventListener('pointercancel', handleUp); + document.addEventListener('pointerleave', handleUp); + return () => { + element.removeEventListener('pointerdown', handleDown); + document.removeEventListener('pointermove', handlePan); + document.removeEventListener('pointerup', handleUp); + document.removeEventListener('pointercancel', handleUp); + document.removeEventListener('pointerleave', handleUp); + }; + }, [ + instance, + svgRef, + isDraggingRef, + setIsInteracting, + isPanEnabled, + options, + drawingArea.width, + drawingArea.height, + setZoomDataCallback, + store, + ]); + + // Add event for chart zoom in/out React.useEffect(() => { const element = svgRef.current; if (element === null || !isZoomEnabled) { @@ -243,7 +342,6 @@ export const useChartProZoom: ChartPlugin = ({ }; }, [ svgRef, - setZoomData, drawingArea, isZoomEnabled, options, @@ -252,7 +350,11 @@ export const useChartProZoom: ChartPlugin = ({ setZoomDataCallback, ]); - return {}; + return { + instance: { + setZoomData: setZoomDataCallback, + }, + }; }; useChartProZoom.params = { @@ -286,12 +388,6 @@ useChartProZoom.getDefaultizedParams = ({ params }) => { }; }; -// useChartProZoom.models = { -// zoom: { -// getDefaultValue: (params) => initializeZoomData(params.options), -// }, -// }; - useChartProZoom.getInitialState = (params) => { return { zoom: { diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts index afc4091a2d66..f90ad8dfce8d 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts @@ -37,7 +37,7 @@ export interface UseChartProZoomState { options: Record; /** * Whether the user is currently interacting with the chart. - * This is useful to prevent animations from running while the user is interacting. + * This is useful to disable animations while the user is interacting. */ isInteracting: boolean; /** @@ -47,7 +47,14 @@ export interface UseChartProZoomState { }; } -export interface UseChartProZoomInstance {} +export interface UseChartProZoomInstance { + /** + * Set the zoom data state. + * @param {ZoomData[] | ((prev: ZoomData[]) => ZoomData[])} value The new value. Can either be the new zoom data, or an updater function. + * @returns {void} + */ + setZoomData: (value: ZoomData[] | ((prev: ZoomData[]) => ZoomData[])) => void; +} export type UseChartProZoomSignature = ChartPluginSignature<{ params: UseChartProZoomParameters; From 6dc78ba9d50215cde5c652c3b7dfb5f212456ab2 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 11:01:13 +0100 Subject: [PATCH 19/32] bring back series colors --- .../src/ChartsTooltip/useAxisTooltip.tsx | 2 +- .../src/ChartsTooltip/useItemTooltip.tsx | 2 +- .../ChartProvider/ChartProvider.types.ts | 4 ++ .../ChartProvider/useColorProcessor.ts | 40 +++++++++++++++++++ .../PluginProvider/useColorProcessor.ts | 20 ---------- .../x-charts/src/internals/store/useCharts.ts | 3 +- 6 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 packages/x-charts/src/context/ChartProvider/useColorProcessor.ts delete mode 100644 packages/x-charts/src/context/PluginProvider/useColorProcessor.ts diff --git a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx index 3bbdc41e20d3..0a37b477f691 100644 --- a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import { useSeries } from '../hooks/useSeries'; -import { useColorProcessor } from '../context/PluginProvider/useColorProcessor'; +import { useColorProcessor } from '../context/ChartProvider/useColorProcessor'; import { SeriesId } from '../models/seriesType/common'; import { CartesianChartSeriesType, ChartsSeriesConfig } from '../models/seriesType/config'; import { useStore } from '../internals/store/useStore'; diff --git a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx index f34c5ba83765..9ad3040ae531 100644 --- a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import { useSeries } from '../hooks/useSeries'; -import { useColorProcessor } from '../context/PluginProvider/useColorProcessor'; +import { useColorProcessor } from '../context/ChartProvider/useColorProcessor'; import { ChartItemIdentifier, ChartSeriesDefaultized, diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index 70254d8adc23..cfe9e5124288 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -31,6 +31,10 @@ export type ChartContextValue< * The ref to the . */ svgRef: React.RefObject; + /** + * The mapping of series type to their processors (extremum getter, color getter, formatter). + */ + seriesConfig: ChartSeriesConfig; }; export interface ChartProviderProps< diff --git a/packages/x-charts/src/context/ChartProvider/useColorProcessor.ts b/packages/x-charts/src/context/ChartProvider/useColorProcessor.ts new file mode 100644 index 000000000000..16bfae239cf9 --- /dev/null +++ b/packages/x-charts/src/context/ChartProvider/useColorProcessor.ts @@ -0,0 +1,40 @@ +'use client'; +import * as React from 'react'; +import { ChartSeriesType } from '../../models/seriesType/config'; +import { useChartContext } from './useChartContext'; +import { DefaultizedSeriesType } from '../../models/seriesType'; +import { AxisDefaultized } from '../../models/axis'; +import { ZAxisDefaultized } from '../../models/z-axis'; + +export type ColorProcessor = ( + series: DefaultizedSeriesType, + xAxis?: AxisDefaultized, + yAxis?: AxisDefaultized, + zAxis?: ZAxisDefaultized, +) => (dataIndex: number) => string; + +export type ColorProcessorsConfig = { + [Key in T]?: ColorProcessor; +}; + +export function useColorProcessor( + seriesType: T, +): ColorProcessorsConfig[T]; +export function useColorProcessor(): ColorProcessorsConfig; +export function useColorProcessor(seriesType?: ChartSeriesType) { + const context = useChartContext(); + + const colorProcessors = React.useMemo(() => { + const rep: ColorProcessorsConfig = {}; + Object.keys(context.seriesConfig).forEach((seriesT) => { + rep[seriesT as ChartSeriesType] = context.seriesConfig[seriesT].colorProcessor; + }); + return rep; + }, [context.seriesConfig]); + + if (!seriesType) { + return colorProcessors; + } + + return colorProcessors[seriesType]; +} diff --git a/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts b/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts deleted file mode 100644 index e84376b4de38..000000000000 --- a/packages/x-charts/src/context/PluginProvider/useColorProcessor.ts +++ /dev/null @@ -1,20 +0,0 @@ -export function useColorProcessor() { - return { - line: - (..._: any) => - (__?: number) => - 'black', - bar: - (..._: any) => - (__?: number) => - 'black', - scatter: - (..._: any) => - (__?: number) => - 'black', - pie: - (..._: any) => - (__?: number) => - 'black', - }; -} diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index 09ce3094f2d2..e937c4e70b99 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -125,8 +125,9 @@ export function useCharts< publicAPI, instance, svgRef: innerSvgRef, + seriesConfig, }), - [instance, publicAPI], + [instance, publicAPI, seriesConfig], ); return { contextValue }; From 2f088e6d05ab6a7a2a50f95ae6686598c05e001b Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 11:07:58 +0100 Subject: [PATCH 20/32] propagate series config --- .../x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx | 1 - .../src/ChartContainerPro/useChartContainerProProps.ts | 1 - packages/x-charts/src/ChartContainer/useChartContainerProps.ts | 2 ++ .../src/context/ChartDataProvider/useChartDataProviderProps.ts | 2 ++ 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 52bd26f3b82d..94994b0bb871 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -1,6 +1,5 @@ 'use client'; import * as React from 'react'; -import PropTypes from 'prop-types'; import type {} from '../typeOverloads'; import { Watermark } from '@mui/x-license/Watermark'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index de62cf9ad077..ec68e911baf9 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -49,7 +49,6 @@ export const useChartContainerProProps = >, diff --git a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts index 281a464ed2ec..3b61918ded9d 100644 --- a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts +++ b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts @@ -40,6 +40,7 @@ export const useChartContainerProps = , 'children'> = { plugins, + seriesConfig, pluginParams: { width, height, From c2261ccb6815cc21e9899c4906e7678b31ec9d36 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 11:33:48 +0100 Subject: [PATCH 21/32] fix ts --- docs/data/charts/zoom-and-pan/ZoomControlled.tsx | 2 +- packages/x-charts-pro/src/models/index.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/data/charts/zoom-and-pan/ZoomControlled.tsx b/docs/data/charts/zoom-and-pan/ZoomControlled.tsx index e76583385576..21c3f54f990f 100644 --- a/docs/data/charts/zoom-and-pan/ZoomControlled.tsx +++ b/docs/data/charts/zoom-and-pan/ZoomControlled.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; -import { ZoomData } from '@mui/x-charts-pro/context'; +import { ZoomData } from '@mui/x-charts-pro/models'; import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; diff --git a/packages/x-charts-pro/src/models/index.ts b/packages/x-charts-pro/src/models/index.ts index d06c5e1be13a..ef57560aea7f 100644 --- a/packages/x-charts-pro/src/models/index.ts +++ b/packages/x-charts-pro/src/models/index.ts @@ -1 +1,2 @@ +export type { ZoomData } from '@mui/x-charts/internals'; export * from './seriesType'; From 956f63f0d77eef713690a8d35c09d3bb5d412ca8 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 13:18:01 +0100 Subject: [PATCH 22/32] run script --- docs/pages/x/api/charts/bar-chart-pro.json | 23 ++++++++- .../x/api/charts/chart-container-pro.json | 51 +------------------ docs/pages/x/api/charts/chart-container.json | 51 +------------------ docs/pages/x/api/charts/heatmap.json | 4 +- docs/pages/x/api/charts/line-chart-pro.json | 23 ++++++++- .../pages/x/api/charts/scatter-chart-pro.json | 17 ++++++- .../charts/bar-chart-pro/bar-chart-pro.json | 8 ++- .../chart-container-pro.json | 44 +--------------- .../chart-container/chart-container.json | 42 +-------------- .../charts/line-chart-pro/line-chart-pro.json | 8 ++- .../scatter-chart-pro/scatter-chart-pro.json | 7 ++- scripts/x-charts-pro.exports.json | 8 +-- 12 files changed, 85 insertions(+), 201 deletions(-) diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index 9eb4f5472810..fd90bd6bafa5 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -74,6 +74,13 @@ "describedArgs": ["event", "barItemIdentifier"] } }, + "onZoomChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(zoomData: Array) => void", + "describedArgs": ["zoomData"] + } + }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -93,13 +100,25 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + } + }, + "zAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" + } + }, + "zoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" } } }, diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index bab8cc8f9c73..d291f4a5586a 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -1,54 +1,5 @@ { - "props": { - "colors": { - "type": { "name": "union", "description": "Array<string>
| func" }, - "default": "blueberryTwilightPalette" - }, - "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, - "height": { "type": { "name": "number" } }, - "highlightedItem": { - "type": { - "name": "shape", - "description": "{ dataIndex?: number, seriesId?: number
| string }" - } - }, - "id": { "type": { "name": "string" } }, - "margin": { - "type": { - "name": "shape", - "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - } - }, - "onHighlightChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(highlightedItem: HighlightItemData | null) => void", - "describedArgs": ["highlightedItem"] - } - }, - "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "skipAnimation": { "type": { "name": "bool" } }, - "width": { "type": { "name": "number" } }, - "xAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" - } - }, - "yAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" - } - }, - "zAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" - } - } - }, + "props": {}, "name": "ChartContainerPro", "imports": [ "import { ChartContainerPro } from '@mui/x-charts-pro/ChartContainerPro';", diff --git a/docs/pages/x/api/charts/chart-container.json b/docs/pages/x/api/charts/chart-container.json index f287b65dc913..8ceb663767e1 100644 --- a/docs/pages/x/api/charts/chart-container.json +++ b/docs/pages/x/api/charts/chart-container.json @@ -1,54 +1,5 @@ { - "props": { - "colors": { - "type": { "name": "union", "description": "Array<string>
| func" }, - "default": "blueberryTwilightPalette" - }, - "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, - "height": { "type": { "name": "number" } }, - "highlightedItem": { - "type": { - "name": "shape", - "description": "{ dataIndex?: number, seriesId?: number
| string }" - } - }, - "id": { "type": { "name": "string" } }, - "margin": { - "type": { - "name": "shape", - "description": "{ bottom?: number, left?: number, right?: number, top?: number }" - } - }, - "onHighlightChange": { - "type": { "name": "func" }, - "signature": { - "type": "function(highlightedItem: HighlightItemData | null) => void", - "describedArgs": ["highlightedItem"] - } - }, - "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, - "skipAnimation": { "type": { "name": "bool" } }, - "width": { "type": { "name": "number" } }, - "xAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" - } - }, - "yAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" - } - }, - "zAxis": { - "type": { - "name": "arrayOf", - "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" - } - } - }, + "props": {}, "name": "ChartContainer", "imports": [ "import { ChartContainer } from '@mui/x-charts/ChartContainer';", diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index 43da11376cb8..3a6ef465ea85 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -7,14 +7,14 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ barGapRatio?: number, categoryGapRatio?: number, classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" }, "required": true }, diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index bdeb28662cdb..ff5c974ca9d6 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -67,6 +67,13 @@ }, "onLineClick": { "type": { "name": "func" } }, "onMarkClick": { "type": { "name": "func" } }, + "onZoomChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(zoomData: Array) => void", + "describedArgs": ["zoomData"] + } + }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -86,13 +93,25 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + } + }, + "zAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" + } + }, + "zoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" } } }, diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index f52fb073e388..b507cc8239ed 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -63,6 +63,13 @@ "describedArgs": ["event", "scatterItemIdentifier"] } }, + "onZoomChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(zoomData: Array) => void", + "describedArgs": ["zoomData"] + } + }, "rightAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -83,13 +90,13 @@ "xAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "yAxis": { "type": { "name": "arrayOf", - "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'empty'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" } }, "zAxis": { @@ -97,6 +104,12 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } + }, + "zoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } } }, "name": "ScatterChartPro", diff --git a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json index 83f1f673b7dc..94ab882e9674 100644 --- a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json +++ b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json @@ -56,6 +56,10 @@ "barItemIdentifier": "The bar item identifier." } }, + "onZoomChange": { + "description": "Callback fired when the zoom has changed.", + "typeDescriptions": { "zoomData": "Updated zoom data." } + }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -78,7 +82,9 @@ }, "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - } + }, + "zAxis": { "description": "The configuration of the z-axes." }, + "zoom": { "description": "The list of zoom data related to each axis." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json index b2a482ebb7fc..68e96af35179 100644 --- a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json +++ b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json @@ -1,45 +1,5 @@ { - "componentDescription": "", - "propDescriptions": { - "colors": { "description": "Color palette used to colorize multiple series." }, - "dataset": { - "description": "An array of objects that can be used to populate series and axes data using their dataKey property." - }, - "disableAxisListener": { - "description": "If true, the charts will not listen to the mouse move event. It might break interactive features, but will improve performance." - }, - "height": { - "description": "The height of the chart in px. If not defined, it takes the height of the parent element." - }, - "highlightedItem": { - "description": "The item currently highlighted. Turns highlighting into a controlled prop." - }, - "id": { - "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." - }, - "margin": { - "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." - }, - "onHighlightChange": { - "description": "The callback fired when the highlighted item changes.", - "typeDescriptions": { "highlightedItem": "The newly highlighted item." } - }, - "series": { - "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." - }, - "skipAnimation": { - "description": "If true, animations are skipped. If unset or false, the animations respects the user's prefers-reduced-motion setting." - }, - "width": { - "description": "The width of the chart in px. If not defined, it takes the width of the parent element." - }, - "xAxis": { - "description": "The configuration of the x-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "yAxis": { - "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "zAxis": { "description": "The configuration of the z-axes." } - }, + "componentDescription": "It sets up the data providers as well as the `` for the chart.\n\nThis is a combination of both the `ChartDataProvider` and `ChartsSurface` components.", + "propDescriptions": {}, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/chart-container/chart-container.json b/docs/translations/api-docs/charts/chart-container/chart-container.json index 954410893680..68e96af35179 100644 --- a/docs/translations/api-docs/charts/chart-container/chart-container.json +++ b/docs/translations/api-docs/charts/chart-container/chart-container.json @@ -1,45 +1,5 @@ { "componentDescription": "It sets up the data providers as well as the `` for the chart.\n\nThis is a combination of both the `ChartDataProvider` and `ChartsSurface` components.", - "propDescriptions": { - "colors": { "description": "Color palette used to colorize multiple series." }, - "dataset": { - "description": "An array of objects that can be used to populate series and axes data using their dataKey property." - }, - "disableAxisListener": { - "description": "If true, the charts will not listen to the mouse move event. It might break interactive features, but will improve performance." - }, - "height": { - "description": "The height of the chart in px. If not defined, it takes the height of the parent element." - }, - "highlightedItem": { - "description": "The item currently highlighted. Turns highlighting into a controlled prop." - }, - "id": { - "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." - }, - "margin": { - "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." - }, - "onHighlightChange": { - "description": "The callback fired when the highlighted item changes.", - "typeDescriptions": { "highlightedItem": "The newly highlighted item." } - }, - "series": { - "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." - }, - "skipAnimation": { - "description": "If true, animations are skipped. If unset or false, the animations respects the user's prefers-reduced-motion setting." - }, - "width": { - "description": "The width of the chart in px. If not defined, it takes the width of the parent element." - }, - "xAxis": { - "description": "The configuration of the x-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "yAxis": { - "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - }, - "zAxis": { "description": "The configuration of the z-axes." } - }, + "propDescriptions": {}, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json index 958fa4e9d53f..618f403e42ea 100644 --- a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json +++ b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json @@ -53,6 +53,10 @@ }, "onLineClick": { "description": "Callback fired when a line element is clicked." }, "onMarkClick": { "description": "Callback fired when a mark element is clicked." }, + "onZoomChange": { + "description": "Callback fired when the zoom has changed.", + "typeDescriptions": { "zoomData": "Updated zoom data." } + }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -73,7 +77,9 @@ }, "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." - } + }, + "zAxis": { "description": "The configuration of the z-axes." }, + "zoom": { "description": "The list of zoom data related to each axis." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json index b8aef3d5b557..d62674842fb5 100644 --- a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json +++ b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json @@ -47,6 +47,10 @@ "scatterItemIdentifier": "The scatter item identifier." } }, + "onZoomChange": { + "description": "Callback fired when the zoom has changed.", + "typeDescriptions": { "zoomData": "Updated zoom data." } + }, "rightAxis": { "description": "Indicate which axis to display the right of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -73,7 +77,8 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." } + "zAxis": { "description": "The configuration of the z-axes." }, + "zoom": { "description": "The list of zoom data related to each axis." } }, "classDescriptions": {} } diff --git a/scripts/x-charts-pro.exports.json b/scripts/x-charts-pro.exports.json index 03bfb2878b6e..7b23d96024d2 100644 --- a/scripts/x-charts-pro.exports.json +++ b/scripts/x-charts-pro.exports.json @@ -315,12 +315,6 @@ { "name": "useYColorScale", "kind": "Function" }, { "name": "useYScale", "kind": "Function" }, { "name": "useZColorScale", "kind": "Function" }, - { "name": "useZoom", "kind": "Function" }, { "name": "ZAxisContextProvider", "kind": "Function" }, - { "name": "ZAxisContextProviderProps", "kind": "TypeAlias" }, - { "name": "ZoomData", "kind": "TypeAlias" }, - { "name": "ZoomOptions", "kind": "TypeAlias" }, - { "name": "ZoomProps", "kind": "TypeAlias" }, - { "name": "ZoomSetup", "kind": "Function" }, - { "name": "ZoomState", "kind": "TypeAlias" } + { "name": "ZAxisContextProviderProps", "kind": "TypeAlias" } ] From 15ef21c78336ece88295a97423a1bedfde0a6caa Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 14:36:59 +0100 Subject: [PATCH 23/32] Remove plugins from proptypes to avoid wrong type resolution --- docs/scripts/generateProptypes.ts | 3 +++ .../src/ChartContainerPro/useChartContainerProProps.ts | 2 +- .../src/context/ChartDataProvider/ChartDataProvider.tsx | 4 +--- .../x-charts/src/context/ChartProvider/ChartProvider.tsx | 8 +++++++- .../src/context/ChartProvider/ChartProvider.types.ts | 3 +++ 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index 3e1c482cefba..eb8f2a163206 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -117,6 +117,9 @@ async function generateProptypes(project: XTypeScriptProject, sourceFile: string if (['children', 'state'].includes(prop.name) && component.name.startsWith('DataGrid')) { return false; } + if (['plugins'].includes(prop.name) && component.name.startsWith('Chart')) { + return false; + } let shouldExclude = false; if (prop.propType.type === 'InterfaceNode') { diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index ec68e911baf9..afc7c2179360 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -49,7 +49,7 @@ export const useChartContainerProProps = >, // eslint-disable-next-line react-compiler/react-compiler diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 7f90dfee1265..78b04b71cec2 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -23,8 +23,7 @@ export type ChartDataProviderProps< ChartProviderProps['pluginParams'], 'children' > & - Pick, 'seriesConfig'> & { - plugins?: ChartProviderProps['plugins']; + Pick, 'seriesConfig' | 'plugins'> & { children?: React.ReactNode; }; @@ -118,7 +117,6 @@ ChartDataProvider.propTypes = { * @param {HighlightItemData | null} highlightedItem The newly highlighted item. */ onHighlightChange: PropTypes.any, - plugins: PropTypes.object, /** * The array of series to display. * Each type of series has its own specificity. diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx index 525f8696a151..2bc17b87e380 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.tsx @@ -8,6 +8,8 @@ import { ConvertSignaturesIntoPlugins, } from '../../internals/plugins/models'; import { ChartSeriesConfig } from '../../internals/plugins/models/seriesConfig'; +import { useChartCartesianAxis } from '../../internals/plugins/featurePlugins/useChartCartesianAxis'; +import { useChartInteraction } from '../../internals/plugins/featurePlugins/useChartInteraction'; import { plugin as barPlugin } from '../../BarChart/plugin'; import { plugin as scatterPlugin } from '../../ScatterChart/plugin'; import { plugin as linePlugin } from '../../LineChart/plugin'; @@ -21,13 +23,17 @@ export const defaultSeriesConfig: ChartSeriesConfig<'bar' | 'scatter' | 'line' | pie: piePlugin, }; +// For consistency with the v7, the cartesian axes are set by default. +// To remove them, you can provide a `plugins` props. +const defaultPlugins = [useChartCartesianAxis, useChartInteraction]; + function ChartProvider< TSignatures extends readonly ChartAnyPluginSignature[], TSeriesType extends ChartSeriesType, >(props: ChartProviderProps) { const { children, - plugins = [] as ConvertSignaturesIntoPlugins, + plugins = defaultPlugins as unknown as ConvertSignaturesIntoPlugins, pluginParams = {}, seriesConfig = defaultSeriesConfig as ChartSeriesConfig, } = props; diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index cfe9e5124288..0fa4d3bae08b 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -41,6 +41,9 @@ export interface ChartProviderProps< TSignatures extends readonly ChartAnyPluginSignature[], TSeries extends ChartSeriesType = ChartSeriesType, > { + /** + * Array of plugins used to add features to the chart. + */ plugins?: ConvertSignaturesIntoPlugins; pluginParams?: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; seriesConfig?: ChartSeriesConfig; From c34d9e4b0b10817afebdd7435aeb82253db54dc0 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 15:35:02 +0100 Subject: [PATCH 24/32] fic rsc --- packages/x-charts/src/context/PolarProvider/PolarProvider.tsx | 1 + packages/x-charts/src/context/PolarProvider/usePolarContext.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx b/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx index 2893ed0d5943..cefe5df6d16c 100644 --- a/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx +++ b/packages/x-charts/src/context/PolarProvider/PolarProvider.tsx @@ -1,3 +1,4 @@ +'use client'; // 'use client'; // import * as React from 'react'; // import { computeAxisValue } from '../../internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue'; diff --git a/packages/x-charts/src/context/PolarProvider/usePolarContext.ts b/packages/x-charts/src/context/PolarProvider/usePolarContext.ts index bd849000ea6f..988d444d0b12 100644 --- a/packages/x-charts/src/context/PolarProvider/usePolarContext.ts +++ b/packages/x-charts/src/context/PolarProvider/usePolarContext.ts @@ -1,3 +1,4 @@ +'use client'; // 'use client'; // import * as React from 'react'; // import { PolarContext } from './PolarContext'; From 992ab59aea6d5b38ff81c9c8f0e33afa3191f465 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 16:05:47 +0100 Subject: [PATCH 25/32] Avoid duplicated series config --- .../src/ChartsTooltip/useAxisTooltip.tsx | 2 +- .../src/ChartsTooltip/useItemTooltip.tsx | 2 +- .../useChartSeries}/useColorProcessor.ts | 25 +++++++++++-------- .../x-charts/src/internals/store/useCharts.ts | 3 +-- 4 files changed, 18 insertions(+), 14 deletions(-) rename packages/x-charts/src/{context/ChartProvider => internals/plugins/corePlugins/useChartSeries}/useColorProcessor.ts (52%) diff --git a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx index 0a37b477f691..72be7e14a751 100644 --- a/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useAxisTooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import { useSeries } from '../hooks/useSeries'; -import { useColorProcessor } from '../context/ChartProvider/useColorProcessor'; +import { useColorProcessor } from '../internals/plugins/corePlugins/useChartSeries/useColorProcessor'; import { SeriesId } from '../models/seriesType/common'; import { CartesianChartSeriesType, ChartsSeriesConfig } from '../models/seriesType/config'; import { useStore } from '../internals/store/useStore'; diff --git a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx index 9ad3040ae531..ed58a96bbd38 100644 --- a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import { useSeries } from '../hooks/useSeries'; -import { useColorProcessor } from '../context/ChartProvider/useColorProcessor'; +import { useColorProcessor } from '../internals/plugins/corePlugins/useChartSeries/useColorProcessor'; import { ChartItemIdentifier, ChartSeriesDefaultized, diff --git a/packages/x-charts/src/context/ChartProvider/useColorProcessor.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useColorProcessor.ts similarity index 52% rename from packages/x-charts/src/context/ChartProvider/useColorProcessor.ts rename to packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useColorProcessor.ts index 16bfae239cf9..229299c06335 100644 --- a/packages/x-charts/src/context/ChartProvider/useColorProcessor.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useColorProcessor.ts @@ -1,10 +1,12 @@ 'use client'; import * as React from 'react'; -import { ChartSeriesType } from '../../models/seriesType/config'; -import { useChartContext } from './useChartContext'; -import { DefaultizedSeriesType } from '../../models/seriesType'; -import { AxisDefaultized } from '../../models/axis'; -import { ZAxisDefaultized } from '../../models/z-axis'; +import { ChartSeriesType } from '../../../../models/seriesType/config'; +import { DefaultizedSeriesType } from '../../../../models/seriesType'; +import { AxisDefaultized } from '../../../../models/axis'; +import { ZAxisDefaultized } from '../../../../models/z-axis'; +import { useSelector } from '../../../store/useSelector'; +import { useStore } from '../../../store/useStore'; +import { selectorChartSeriesConfig } from './useChartSeries.selectors'; export type ColorProcessor = ( series: DefaultizedSeriesType, @@ -22,15 +24,18 @@ export function useColorProcessor( ): ColorProcessorsConfig[T]; export function useColorProcessor(): ColorProcessorsConfig; export function useColorProcessor(seriesType?: ChartSeriesType) { - const context = useChartContext(); + const store = useStore(); + const seriesConfig = useSelector(store, selectorChartSeriesConfig); const colorProcessors = React.useMemo(() => { const rep: ColorProcessorsConfig = {}; - Object.keys(context.seriesConfig).forEach((seriesT) => { - rep[seriesT as ChartSeriesType] = context.seriesConfig[seriesT].colorProcessor; - }); + (Object.keys(seriesConfig) as ChartSeriesType[]).forEach( + (seriesT: T) => { + rep[seriesT] = seriesConfig[seriesT].colorProcessor; + }, + ); return rep; - }, [context.seriesConfig]); + }, [seriesConfig]); if (!seriesType) { return colorProcessors; diff --git a/packages/x-charts/src/internals/store/useCharts.ts b/packages/x-charts/src/internals/store/useCharts.ts index e937c4e70b99..09ce3094f2d2 100644 --- a/packages/x-charts/src/internals/store/useCharts.ts +++ b/packages/x-charts/src/internals/store/useCharts.ts @@ -125,9 +125,8 @@ export function useCharts< publicAPI, instance, svgRef: innerSvgRef, - seriesConfig, }), - [instance, publicAPI, seriesConfig], + [instance, publicAPI], ); return { contextValue }; From 9b15a358fccd5ef2257f10691823eec3074df031 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 16:11:29 +0100 Subject: [PATCH 26/32] fix tests --- .../useHighlighted.test.tsx | 2 +- .../x-charts/src/hooks/useSeries.test.tsx | 25 +++++++++++-------- .../useChartSeries/useChartSeries.ts | 5 +++- .../useChartSeries/useChartSeries.types.ts | 2 +- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx index 631c6a74aa29..40caf89b0765 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx @@ -47,7 +47,7 @@ describe('useHighlighted', () => { it('should not throw an error when parent context is present', () => { render( - + diff --git a/packages/x-charts/src/hooks/useSeries.test.tsx b/packages/x-charts/src/hooks/useSeries.test.tsx index eb0c562c05cd..37c30c49f312 100644 --- a/packages/x-charts/src/hooks/useSeries.test.tsx +++ b/packages/x-charts/src/hooks/useSeries.test.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { ErrorBoundary, createRenderer, reactMajor, screen } from '@mui/internal-test-utils'; import { useSeries } from './useSeries'; +import { ChartProvider } from '../context/ChartProvider'; function UseSeries() { const { bar } = useSeries(); @@ -20,14 +21,14 @@ describe('useSeries', () => { const errorRef = React.createRef(); - const errorMessage1 = 'MUI X: Could not find the series ref context.'; + const errorMessage1 = 'MUI X: Could not find the Chart context.'; const errorMessage2 = - 'It looks like you rendered your component outside of a ChartsContainer parent component.'; + 'It looks like you rendered your component outside of a ChartDataProvider.'; const errorMessage3 = 'The above error occurred in the component:'; const expextedError = reactMajor < 19 ? [errorMessage1, errorMessage2, errorMessage3] - : `${errorMessage1}\n${errorMessage2}`; + : [errorMessage1, errorMessage2].join('\n'); expect(() => render( @@ -38,18 +39,20 @@ describe('useSeries', () => { ).toErrorDev(expextedError); expect((errorRef.current as any).errors).to.have.length(1); - expect((errorRef.current as any).errors[0].toString()).to.include( - 'MUI X: Could not find the series ref context.', - ); + expect((errorRef.current as any).errors[0].toString()).to.include(errorMessage1); }); it('should not throw an error when parent context is present', () => { render( - // - // - , - // - // , + + + , ); expect(screen.getByText('test-id')).toBeVisible(); diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts index 2722fe2e3a46..bc07bf574888 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.ts @@ -10,7 +10,7 @@ export const useChartSeries: ChartPlugin = ({ store, seriesConfig, }) => { - const { series = [], dataset, theme, colors } = params; + const { series, dataset, theme, colors } = params; // The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartSeries` // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one @@ -46,7 +46,10 @@ useChartSeries.params = { theme: true, }; +const EMPTY_ARRAY: any[] = []; + useChartSeries.getDefaultizedParams = ({ params }) => ({ + series: EMPTY_ARRAY, ...params, colors: params.colors ?? blueberryTwilightPalette, theme: params.theme ?? 'light', diff --git a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts index 3896fc45ed0a..21b5ed129f34 100644 --- a/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts +++ b/packages/x-charts/src/internals/plugins/corePlugins/useChartSeries/useChartSeries.types.ts @@ -27,7 +27,7 @@ export type UseChartSeriesDefaultizedParameters[]; + series: AllSeriesType[]; /** * Color palette used to colorize multiple series. * @default blueberryTwilightPalette From 4d46505fb7c84964b0b568eeec6a99780ff06a55 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 17 Dec 2024 23:54:56 +0100 Subject: [PATCH 27/32] fix ts --- .../x-charts/src/context/ChartProvider/ChartProvider.types.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index 0fa4d3bae08b..60069c614670 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -31,10 +31,6 @@ export type ChartContextValue< * The ref to the . */ svgRef: React.RefObject; - /** - * The mapping of series type to their processors (extremum getter, color getter, formatter). - */ - seriesConfig: ChartSeriesConfig; }; export interface ChartProviderProps< From b4ce8a1c3556bd40f7648e90254ea1ed4af4c4fd Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 18 Dec 2024 00:41:33 +0100 Subject: [PATCH 28/32] fix-import --- .../useChartCartesianAxis/createAxisFilterMapper.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts index 4eb52d14dacf..bcc9b679fa91 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/createAxisFilterMapper.ts @@ -8,6 +8,7 @@ import { ChartSeriesConfig } from '../../models/seriesConfig'; import { getAxisExtremum } from './getAxisExtremum'; import { DefaultizedZoomOption, ExtremumFilter } from './useChartCartesianAxis.types'; import { GetZoomAxisFilters, ZoomAxisFilters, ZoomData } from './zoom.types'; +import { getScale } from '../../../getScale'; type CreateAxisFilterMapperParams = { zoomMap: Map; @@ -50,8 +51,10 @@ export const createAxisFilterMapper = let min: number | Date; let max: number | Date; - // @ts-expect-error The function defaults to linear scale if the scaleType is not recognized. - [min, max] = getScale(scaleType, extremums, [0, 100]).nice().domain(); + const continuousScaleType = + !scaleType || scaleType === 'band' || scaleType === 'point' ? 'linear' : scaleType; + + [min, max] = getScale(continuousScaleType, extremums, [0, 100]).nice().domain(); min = min instanceof Date ? min.getTime() : min; max = max instanceof Date ? max.getTime() : max; From b8b7942df12652fc462ee41688ff15f469aed923 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 18 Dec 2024 11:44:29 +0100 Subject: [PATCH 29/32] bring back chart container proprtypes --- .../x/api/charts/chart-container-pro.json | 64 +++- docs/pages/x/api/charts/chart-container.json | 51 ++- docs/scripts/generateProptypes.ts | 2 +- .../chart-container-pro.json | 47 ++- .../chart-container/chart-container.json | 42 ++- .../ChartContainerPro/ChartContainerPro.tsx | 310 ++++++++++++++++++ .../src/ChartContainer/ChartContainer.tsx | 271 +++++++++++++++ 7 files changed, 782 insertions(+), 5 deletions(-) diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index d291f4a5586a..3dfbc86a9076 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -1,5 +1,67 @@ { - "props": {}, + "props": { + "colors": { + "type": { "name": "union", "description": "Array<string>
| func" }, + "default": "blueberryTwilightPalette" + }, + "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, + "height": { "type": { "name": "number" } }, + "highlightedItem": { + "type": { + "name": "shape", + "description": "{ dataIndex?: number, seriesId?: number
| string }" + } + }, + "id": { "type": { "name": "string" } }, + "margin": { + "type": { + "name": "shape", + "description": "{ bottom?: number, left?: number, right?: number, top?: number }" + } + }, + "onHighlightChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(highlightedItem: HighlightItemData | null) => void", + "describedArgs": ["highlightedItem"] + } + }, + "onZoomChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(zoomData: Array) => void", + "describedArgs": ["zoomData"] + } + }, + "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "skipAnimation": { "type": { "name": "bool" } }, + "width": { "type": { "name": "number" } }, + "xAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + } + }, + "yAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func, zoom?: { filterMode: 'discard'
| 'keep', maxEnd?: number, maxSpan?: number, minSpan?: number, minStart?: number, panning?: bool, step?: number }
| bool }>" + } + }, + "zAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" + } + }, + "zoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + } + }, "name": "ChartContainerPro", "imports": [ "import { ChartContainerPro } from '@mui/x-charts-pro/ChartContainerPro';", diff --git a/docs/pages/x/api/charts/chart-container.json b/docs/pages/x/api/charts/chart-container.json index 8ceb663767e1..f287b65dc913 100644 --- a/docs/pages/x/api/charts/chart-container.json +++ b/docs/pages/x/api/charts/chart-container.json @@ -1,5 +1,54 @@ { - "props": {}, + "props": { + "colors": { + "type": { "name": "union", "description": "Array<string>
| func" }, + "default": "blueberryTwilightPalette" + }, + "dataset": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "disableAxisListener": { "type": { "name": "bool" }, "default": "false" }, + "height": { "type": { "name": "number" } }, + "highlightedItem": { + "type": { + "name": "shape", + "description": "{ dataIndex?: number, seriesId?: number
| string }" + } + }, + "id": { "type": { "name": "string" } }, + "margin": { + "type": { + "name": "shape", + "description": "{ bottom?: number, left?: number, right?: number, top?: number }" + } + }, + "onHighlightChange": { + "type": { "name": "func" }, + "signature": { + "type": "function(highlightedItem: HighlightItemData | null) => void", + "describedArgs": ["highlightedItem"] + } + }, + "series": { "type": { "name": "arrayOf", "description": "Array<object>" } }, + "skipAnimation": { "type": { "name": "bool" } }, + "width": { "type": { "name": "number" } }, + "xAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'bottom'
| 'top', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + } + }, + "yAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ classes?: object, colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, disableLine?: bool, disableTicks?: bool, domainLimit?: 'nice'
| 'strict'
| func, fill?: string, hideTooltip?: bool, id?: number
| string, label?: string, labelStyle?: object, max?: Date
| number, min?: Date
| number, position?: 'left'
| 'right', reverse?: bool, scaleType?: 'band'
| 'linear'
| 'log'
| 'point'
| 'pow'
| 'sqrt'
| 'time'
| 'utc', slotProps?: object, slots?: object, stroke?: string, sx?: Array<func
| object
| bool>
| func
| object, tickInterval?: 'auto'
| array
| func, tickLabelInterval?: 'auto'
| func, tickLabelPlacement?: 'middle'
| 'tick', tickLabelStyle?: object, tickMaxStep?: number, tickMinStep?: number, tickNumber?: number, tickPlacement?: 'end'
| 'extremities'
| 'middle'
| 'start', tickSize?: number, valueFormatter?: func }>" + } + }, + "zAxis": { + "type": { + "name": "arrayOf", + "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" + } + } + }, "name": "ChartContainer", "imports": [ "import { ChartContainer } from '@mui/x-charts/ChartContainer';", diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index eb8f2a163206..b0b2475c9e31 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -10,7 +10,7 @@ import { import { fixBabelGeneratorIssues, fixLineEndings } from '@mui/internal-docs-utils'; import { createXTypeScriptProjects, XTypeScriptProject } from './createXTypeScriptProjects'; -const COMPONENTS_WITHOUT_PROPTYPES = ['AnimatedBarElement', 'ChartContainer', 'ChartContainerPro']; +const COMPONENTS_WITHOUT_PROPTYPES = ['AnimatedBarElement']; async function generateProptypes(project: XTypeScriptProject, sourceFile: string) { const isDateObject = (name: string) => { diff --git a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json index 68e96af35179..ae1453986647 100644 --- a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json +++ b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json @@ -1,5 +1,50 @@ { "componentDescription": "It sets up the data providers as well as the `` for the chart.\n\nThis is a combination of both the `ChartDataProvider` and `ChartsSurface` components.", - "propDescriptions": {}, + "propDescriptions": { + "colors": { "description": "Color palette used to colorize multiple series." }, + "dataset": { + "description": "An array of objects that can be used to populate series and axes data using their dataKey property." + }, + "disableAxisListener": { + "description": "If true, the charts will not listen to the mouse move event. It might break interactive features, but will improve performance." + }, + "height": { + "description": "The height of the chart in px. If not defined, it takes the height of the parent element." + }, + "highlightedItem": { + "description": "The item currently highlighted. Turns highlighting into a controlled prop." + }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, + "margin": { + "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." + }, + "onHighlightChange": { + "description": "The callback fired when the highlighted item changes.", + "typeDescriptions": { "highlightedItem": "The newly highlighted item." } + }, + "onZoomChange": { + "description": "Callback fired when the zoom has changed.", + "typeDescriptions": { "zoomData": "Updated zoom data." } + }, + "series": { + "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." + }, + "skipAnimation": { + "description": "If true, animations are skipped. If unset or false, the animations respects the user's prefers-reduced-motion setting." + }, + "width": { + "description": "The width of the chart in px. If not defined, it takes the width of the parent element." + }, + "xAxis": { + "description": "The configuration of the x-axes. If not provided, a default axis config is used. An array of AxisConfig objects." + }, + "yAxis": { + "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." + }, + "zAxis": { "description": "The configuration of the z-axes." }, + "zoom": { "description": "The list of zoom data related to each axis." } + }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/chart-container/chart-container.json b/docs/translations/api-docs/charts/chart-container/chart-container.json index 68e96af35179..954410893680 100644 --- a/docs/translations/api-docs/charts/chart-container/chart-container.json +++ b/docs/translations/api-docs/charts/chart-container/chart-container.json @@ -1,5 +1,45 @@ { "componentDescription": "It sets up the data providers as well as the `` for the chart.\n\nThis is a combination of both the `ChartDataProvider` and `ChartsSurface` components.", - "propDescriptions": {}, + "propDescriptions": { + "colors": { "description": "Color palette used to colorize multiple series." }, + "dataset": { + "description": "An array of objects that can be used to populate series and axes data using their dataKey property." + }, + "disableAxisListener": { + "description": "If true, the charts will not listen to the mouse move event. It might break interactive features, but will improve performance." + }, + "height": { + "description": "The height of the chart in px. If not defined, it takes the height of the parent element." + }, + "highlightedItem": { + "description": "The item currently highlighted. Turns highlighting into a controlled prop." + }, + "id": { + "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." + }, + "margin": { + "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." + }, + "onHighlightChange": { + "description": "The callback fired when the highlighted item changes.", + "typeDescriptions": { "highlightedItem": "The newly highlighted item." } + }, + "series": { + "description": "The array of series to display. Each type of series has its own specificity. Please refer to the appropriate docs page to learn more about it." + }, + "skipAnimation": { + "description": "If true, animations are skipped. If unset or false, the animations respects the user's prefers-reduced-motion setting." + }, + "width": { + "description": "The width of the chart in px. If not defined, it takes the width of the parent element." + }, + "xAxis": { + "description": "The configuration of the x-axes. If not provided, a default axis config is used. An array of AxisConfig objects." + }, + "yAxis": { + "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." + }, + "zAxis": { "description": "The configuration of the z-axes." } + }, "classDescriptions": {} } diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 94994b0bb871..b3ca5395c19e 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import type {} from '../typeOverloads'; import { Watermark } from '@mui/x-license/Watermark'; import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier'; @@ -63,4 +64,313 @@ const ChartContainerPro = React.forwardRef(function ChartContainerProInner< props: ChartContainerProProps & { ref?: React.ForwardedRef }, ) => React.JSX.Element; +// @ts-ignore +ChartContainerPro.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "pnpm proptypes" | + // ---------------------------------------------------------------------- + children: PropTypes.node, + className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), + /** + * An array of objects that can be used to populate series and axes data using their `dataKey` property. + */ + dataset: PropTypes.arrayOf(PropTypes.object), + desc: PropTypes.string, + /** + * If `true`, the charts will not listen to the mouse move event. + * It might break interactive features, but will improve performance. + * @default false + */ + disableAxisListener: PropTypes.bool, + /** + * The height of the chart in px. If not defined, it takes the height of the parent element. + */ + height: PropTypes.number, + /** + * The item currently highlighted. Turns highlighting into a controlled prop. + */ + highlightedItem: PropTypes.shape({ + dataIndex: PropTypes.number, + seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, + /** + * The margin between the SVG and the drawing area. + * It's used for leaving some space for extra information such as the x- and y-axis or legend. + * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. + */ + margin: PropTypes.shape({ + bottom: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + }), + /** + * The callback fired when the highlighted item changes. + * + * @param {HighlightItemData | null} highlightedItem The newly highlighted item. + */ + onHighlightChange: PropTypes.func, + /** + * Callback fired when the zoom has changed. + * + * @param {ZoomData[]} zoomData Updated zoom data. + */ + onZoomChange: PropTypes.func, + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series: PropTypes.arrayOf(PropTypes.object), + seriesConfig: PropTypes.object, + /** + * If `true`, animations are skipped. + * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. + */ + skipAnimation: PropTypes.bool, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + theme: PropTypes.oneOf(['dark', 'light']), + title: PropTypes.string, + /** + * The width of the chart in px. If not defined, it takes the width of the parent element. + */ + width: PropTypes.number, + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['bottom', 'top']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + zoom: PropTypes.oneOfType([ + PropTypes.shape({ + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, + maxEnd: PropTypes.number, + maxSpan: PropTypes.number, + minSpan: PropTypes.number, + minStart: PropTypes.number, + panning: PropTypes.bool, + step: PropTypes.number, + }), + PropTypes.bool, + ]), + }), + ), + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['left', 'right']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + zoom: PropTypes.oneOfType([ + PropTypes.shape({ + filterMode: PropTypes.oneOf(['discard', 'keep']).isRequired, + maxEnd: PropTypes.number, + maxSpan: PropTypes.number, + minSpan: PropTypes.number, + minStart: PropTypes.number, + panning: PropTypes.bool, + step: PropTypes.number, + }), + PropTypes.bool, + ]), + }), + ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), + /** + * The list of zoom data related to each axis. + */ + zoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), +} as any; + export { ChartContainerPro }; diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 3656d66e6780..88065d667704 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { ChartSeriesType } from '../models/seriesType/config'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; import { useChartContainerProps } from './useChartContainerProps'; @@ -55,4 +56,274 @@ const ChartContainer = React.forwardRef(function ChartContainer & { ref?: React.ForwardedRef }, ) => React.JSX.Element; +// @ts-ignore + +ChartContainer.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the TypeScript types and run "pnpm proptypes" | + // ---------------------------------------------------------------------- + children: PropTypes.node, + className: PropTypes.string, + /** + * Color palette used to colorize multiple series. + * @default blueberryTwilightPalette + */ + colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), + /** + * An array of objects that can be used to populate series and axes data using their `dataKey` property. + */ + dataset: PropTypes.arrayOf(PropTypes.object), + desc: PropTypes.string, + /** + * If `true`, the charts will not listen to the mouse move event. + * It might break interactive features, but will improve performance. + * @default false + */ + disableAxisListener: PropTypes.bool, + /** + * The height of the chart in px. If not defined, it takes the height of the parent element. + */ + height: PropTypes.number, + /** + * The item currently highlighted. Turns highlighting into a controlled prop. + */ + highlightedItem: PropTypes.shape({ + dataIndex: PropTypes.number, + seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + }), + /** + * This prop is used to help implement the accessibility logic. + * If you don't provide this prop. It falls back to a randomly generated id. + */ + id: PropTypes.string, + /** + * The margin between the SVG and the drawing area. + * It's used for leaving some space for extra information such as the x- and y-axis or legend. + * Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`. + */ + margin: PropTypes.shape({ + bottom: PropTypes.number, + left: PropTypes.number, + right: PropTypes.number, + top: PropTypes.number, + }), + /** + * The callback fired when the highlighted item changes. + * + * @param {HighlightItemData | null} highlightedItem The newly highlighted item. + */ + onHighlightChange: PropTypes.func, + /** + * The array of series to display. + * Each type of series has its own specificity. + * Please refer to the appropriate docs page to learn more about it. + */ + series: PropTypes.arrayOf(PropTypes.object), + seriesConfig: PropTypes.object, + /** + * If `true`, animations are skipped. + * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. + */ + skipAnimation: PropTypes.bool, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + theme: PropTypes.oneOf(['dark', 'light']), + title: PropTypes.string, + /** + * The width of the chart in px. If not defined, it takes the width of the parent element. + */ + width: PropTypes.number, + /** + * The configuration of the x-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + xAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['bottom', 'top']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + }), + ), + /** + * The configuration of the y-axes. + * If not provided, a default axis config is used. + * An array of [[AxisConfig]] objects. + */ + yAxis: PropTypes.arrayOf( + PropTypes.shape({ + classes: PropTypes.object, + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + disableLine: PropTypes.bool, + disableTicks: PropTypes.bool, + domainLimit: PropTypes.oneOfType([PropTypes.oneOf(['nice', 'strict']), PropTypes.func]), + fill: PropTypes.string, + hideTooltip: PropTypes.bool, + id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), + label: PropTypes.string, + labelStyle: PropTypes.object, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + position: PropTypes.oneOf(['left', 'right']), + reverse: PropTypes.bool, + scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']), + slotProps: PropTypes.object, + slots: PropTypes.object, + stroke: PropTypes.string, + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + tickInterval: PropTypes.oneOfType([ + PropTypes.oneOf(['auto']), + PropTypes.array, + PropTypes.func, + ]), + tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]), + tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']), + tickLabelStyle: PropTypes.object, + tickMaxStep: PropTypes.number, + tickMinStep: PropTypes.number, + tickNumber: PropTypes.number, + tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']), + tickSize: PropTypes.number, + valueFormatter: PropTypes.func, + }), + ), + /** + * The configuration of the z-axes. + */ + zAxis: PropTypes.arrayOf( + PropTypes.shape({ + colorMap: PropTypes.oneOfType([ + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + type: PropTypes.oneOf(['ordinal']).isRequired, + unknownColor: PropTypes.string, + values: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]) + .isRequired, + ), + }), + PropTypes.shape({ + color: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.string.isRequired), + PropTypes.func, + ]).isRequired, + max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]), + type: PropTypes.oneOf(['continuous']).isRequired, + }), + PropTypes.shape({ + colors: PropTypes.arrayOf(PropTypes.string).isRequired, + thresholds: PropTypes.arrayOf( + PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired, + ).isRequired, + type: PropTypes.oneOf(['piecewise']).isRequired, + }), + ]), + data: PropTypes.array, + dataKey: PropTypes.string, + id: PropTypes.string, + max: PropTypes.number, + min: PropTypes.number, + }), + ), +} as any; + export { ChartContainer }; From 132bd85ab2be927a61e4e41e4d929b310ff41486 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 18 Dec 2024 11:52:39 +0100 Subject: [PATCH 30/32] remove unused props type from gauge --- docs/pages/x/api/charts/gauge-container.json | 4 ---- docs/pages/x/api/charts/gauge.json | 4 ---- .../charts/gauge-container/gauge-container.json | 1 - docs/translations/api-docs/charts/gauge/gauge.json | 1 - packages/x-charts/src/Gauge/Gauge.tsx | 7 ------- packages/x-charts/src/Gauge/GaugeContainer.tsx | 12 ++++-------- 6 files changed, 4 insertions(+), 25 deletions(-) diff --git a/docs/pages/x/api/charts/gauge-container.json b/docs/pages/x/api/charts/gauge-container.json index 546197e72781..6a87a9499c1e 100644 --- a/docs/pages/x/api/charts/gauge-container.json +++ b/docs/pages/x/api/charts/gauge-container.json @@ -1,9 +1,5 @@ { "props": { - "colors": { - "type": { "name": "union", "description": "Array<string>
| func" }, - "default": "blueberryTwilightPalette" - }, "cornerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "0" diff --git a/docs/pages/x/api/charts/gauge.json b/docs/pages/x/api/charts/gauge.json index 177bdfb34ad0..145b8f21cd1d 100644 --- a/docs/pages/x/api/charts/gauge.json +++ b/docs/pages/x/api/charts/gauge.json @@ -1,9 +1,5 @@ { "props": { - "colors": { - "type": { "name": "union", "description": "Array<string>
| func" }, - "default": "blueberryTwilightPalette" - }, "cornerRadius": { "type": { "name": "union", "description": "number
| string" }, "default": "0" diff --git a/docs/translations/api-docs/charts/gauge-container/gauge-container.json b/docs/translations/api-docs/charts/gauge-container/gauge-container.json index 29df208ed271..c48197957aac 100644 --- a/docs/translations/api-docs/charts/gauge-container/gauge-container.json +++ b/docs/translations/api-docs/charts/gauge-container/gauge-container.json @@ -1,7 +1,6 @@ { "componentDescription": "", "propDescriptions": { - "colors": { "description": "Color palette used to colorize multiple series." }, "cornerRadius": { "description": "The radius applied to arc corners (similar to border radius). Set it to '50%' to get rounded arc." }, diff --git a/docs/translations/api-docs/charts/gauge/gauge.json b/docs/translations/api-docs/charts/gauge/gauge.json index b1b19127feaa..9b2c846d31ba 100644 --- a/docs/translations/api-docs/charts/gauge/gauge.json +++ b/docs/translations/api-docs/charts/gauge/gauge.json @@ -1,7 +1,6 @@ { "componentDescription": "", "propDescriptions": { - "colors": { "description": "Color palette used to colorize multiple series." }, "cornerRadius": { "description": "The radius applied to arc corners (similar to border radius). Set it to '50%' to get rounded arc." }, diff --git a/packages/x-charts/src/Gauge/Gauge.tsx b/packages/x-charts/src/Gauge/Gauge.tsx index d3dff37a4fda..458b4823548a 100644 --- a/packages/x-charts/src/Gauge/Gauge.tsx +++ b/packages/x-charts/src/Gauge/Gauge.tsx @@ -48,11 +48,6 @@ Gauge.propTypes = { children: PropTypes.node, classes: PropTypes.object, className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), /** * The radius applied to arc corners (similar to border radius). * Set it to '50%' to get rounded arc. @@ -71,7 +66,6 @@ Gauge.propTypes = { * The '100%' is the height the drawing area. */ cy: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - dataset: PropTypes.arrayOf(PropTypes.object), desc: PropTypes.string, /** * If `true`, the charts will not listen to the mouse move event. @@ -129,7 +123,6 @@ Gauge.propTypes = { PropTypes.object, ]), text: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), - theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The value of the gauge. diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index ca1f16dcff16..9333ce66d582 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -10,7 +10,10 @@ import { ChartCorePluginSignatures } from '../internals/plugins/corePlugins'; export interface GaugeContainerProps extends Omit, - Omit, 'series'>, + Omit< + MergeSignaturesProperty, + 'series' | 'dataset' | 'colors' | 'theme' + >, Omit, Omit, 'width' | 'height'> { children?: React.ReactNode; @@ -91,11 +94,6 @@ GaugeContainer.propTypes = { // ---------------------------------------------------------------------- children: PropTypes.node, className: PropTypes.string, - /** - * Color palette used to colorize multiple series. - * @default blueberryTwilightPalette - */ - colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]), /** * The radius applied to arc corners (similar to border radius). * Set it to '50%' to get rounded arc. @@ -114,7 +112,6 @@ GaugeContainer.propTypes = { * The '100%' is the height the drawing area. */ cy: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - dataset: PropTypes.arrayOf(PropTypes.object), desc: PropTypes.string, /** * If `true`, the charts will not listen to the mouse move event. @@ -171,7 +168,6 @@ GaugeContainer.propTypes = { PropTypes.func, PropTypes.object, ]), - theme: PropTypes.oneOf(['dark', 'light']), title: PropTypes.string, /** * The value of the gauge. From 14500390ee35f9172b54ed69333802178d8eece6 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 18 Dec 2024 12:27:10 +0100 Subject: [PATCH 31/32] remove seriesConfig --- docs/scripts/generateProptypes.ts | 3 +- .../src/BarChartPro/BarChartPro.tsx | 8 ----- .../ChartContainerPro/ChartContainerPro.tsx | 2 +- packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 35 +++---------------- .../src/LineChartPro/LineChartPro.tsx | 30 ---------------- .../src/ScatterChartPro/ScatterChartPro.tsx | 30 ---------------- packages/x-charts/src/BarChart/BarChart.tsx | 8 ----- .../src/ChartContainer/ChartContainer.tsx | 1 - packages/x-charts/src/LineChart/LineChart.tsx | 24 ------------- packages/x-charts/src/PieChart/PieChart.tsx | 24 ------------- .../src/ScatterChart/ScatterChart.tsx | 24 ------------- .../src/SparkLineChart/SparkLineChart.tsx | 24 ------------- .../ChartDataProvider/ChartDataProvider.tsx | 1 - .../ChartProvider/ChartProvider.types.ts | 4 +++ 14 files changed, 12 insertions(+), 206 deletions(-) diff --git a/docs/scripts/generateProptypes.ts b/docs/scripts/generateProptypes.ts index b0b2475c9e31..d45ba1f6af78 100644 --- a/docs/scripts/generateProptypes.ts +++ b/docs/scripts/generateProptypes.ts @@ -75,6 +75,7 @@ async function generateProptypes(project: XTypeScriptProject, sourceFile: string 'leftAxis', 'rightAxis', 'plugins', + 'seriesConfig', ]; if (propsToNotResolve.includes(name)) { return false; @@ -117,7 +118,7 @@ async function generateProptypes(project: XTypeScriptProject, sourceFile: string if (['children', 'state'].includes(prop.name) && component.name.startsWith('DataGrid')) { return false; } - if (['plugins'].includes(prop.name) && component.name.startsWith('Chart')) { + if (['plugins', 'seriesConfig'].includes(prop.name) && component.name.includes('Chart')) { return false; } let shouldExclude = false; diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 5e3194c38d36..3a6f11ffd0ac 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -257,14 +257,6 @@ BarChartPro.propTypes = { * An array of [[BarSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index b3ca5395c19e..62b6d75f6632 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -65,6 +65,7 @@ const ChartContainerPro = React.forwardRef(function ChartContainerProInner< ) => React.JSX.Element; // @ts-ignore + ChartContainerPro.propTypes = { // ----------------------------- Warning -------------------------------- // | These PropTypes are generated from the TypeScript type definitions | @@ -133,7 +134,6 @@ ChartContainerPro.propTypes = { * Please refer to the appropriate docs page to learn more about it. */ series: PropTypes.arrayOf(PropTypes.object), - seriesConfig: PropTypes.object, /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index f071998b1d29..60b4a70948b3 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -296,36 +296,11 @@ Heatmap.propTypes = { * An array of [[HeatmapSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - heatmap: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), + /** + * The configuration helpers used to compute attributes according to the serries type. + * @ignore Unstable props for internal usage. + */ + seriesConfig: PropTypes.object, /** * The props used for each component slot. * @default {} diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index 8a2b6c751818..01325289b49d 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -329,36 +329,6 @@ LineChartPro.propTypes = { * An array of [[LineSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - heatmap: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * @default false diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index 8b052c633eff..ea75001c4499 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -190,36 +190,6 @@ ScatterChartPro.propTypes = { * An array of [[ScatterSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - heatmap: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index 9e925a99f50a..d42550a7ff06 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -268,14 +268,6 @@ BarChart.propTypes = { * An array of [[BarSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 88065d667704..9f8d02586f84 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -120,7 +120,6 @@ ChartContainer.propTypes = { * Please refer to the appropriate docs page to learn more about it. */ series: PropTypes.arrayOf(PropTypes.object), - seriesConfig: PropTypes.object, /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index bb1e95531a99..9f1ddbd4ffb7 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -302,30 +302,6 @@ LineChart.propTypes = { * An array of [[LineSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * @default false diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index de08de9f78a9..ecf9f2f3cacc 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -209,30 +209,6 @@ PieChart.propTypes = { * An array of [[PieSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index a8c5f1a082ed..4b5cd53b9358 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -257,30 +257,6 @@ ScatterChart.propTypes = { * An array of [[ScatterSeriesType]] objects. */ series: PropTypes.arrayOf(PropTypes.object).isRequired, - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 31cba06113c1..333b81003bc0 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -318,30 +318,6 @@ SparkLineChart.propTypes = { * @default 'line' */ plotType: PropTypes.oneOf(['bar', 'line']), - seriesConfig: PropTypes.shape({ - bar: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - line: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - pie: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - }).isRequired, - scatter: PropTypes.shape({ - colorProcessor: PropTypes.func.isRequired, - seriesProcessor: PropTypes.func.isRequired, - xExtremumGetter: PropTypes.func.isRequired, - yExtremumGetter: PropTypes.func.isRequired, - }).isRequired, - }), /** * Set to `true` to highlight the value. * With line, it shows a point. diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 78b04b71cec2..438977b18d82 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -123,7 +123,6 @@ ChartDataProvider.propTypes = { * Please refer to the appropriate docs page to learn more about it. */ series: PropTypes.any, - seriesConfig: PropTypes.object, /** * If `true`, animations are skipped. * If unset or `false`, the animations respects the user's `prefers-reduced-motion` setting. diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index 60069c614670..82da0aa004e0 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -42,6 +42,10 @@ export interface ChartProviderProps< */ plugins?: ConvertSignaturesIntoPlugins; pluginParams?: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; + /** + * The configuration helpers used to compute attributes according to the serries type. + * @ignore Unstable props for internal usage. + */ seriesConfig?: ChartSeriesConfig; children: React.ReactNode; } From b38dc274e52f5fdb68e818043e303cb85c775211 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 18 Dec 2024 13:33:37 +0100 Subject: [PATCH 32/32] Cleanup zoom API --- .../charts/zoom-and-pan/ZoomControlled.js | 29 +++++++++------ .../charts/zoom-and-pan/ZoomControlled.tsx | 30 +++++++++------ docs/pages/x/api/charts/bar-chart-pro.json | 12 +++--- .../x/api/charts/chart-container-pro.json | 12 +++--- docs/pages/x/api/charts/heatmap.json | 6 +++ docs/pages/x/api/charts/line-chart-pro.json | 12 +++--- .../pages/x/api/charts/scatter-chart-pro.json | 12 +++--- .../charts/bar-chart-pro/bar-chart-pro.json | 4 +- .../chart-container-pro.json | 4 +- .../api-docs/charts/heatmap/heatmap.json | 1 + .../charts/line-chart-pro/line-chart-pro.json | 4 +- .../scatter-chart-pro/scatter-chart-pro.json | 4 +- .../src/BarChartPro/BarChartPro.tsx | 37 ++++++++++++------- .../ChartContainerPro/ChartContainerPro.tsx | 25 ++++++++----- .../useChartContainerProProps.ts | 7 ++-- packages/x-charts-pro/src/Heatmap/Heatmap.tsx | 15 ++++++++ .../src/LineChartPro/LineChartPro.tsx | 37 ++++++++++++------- .../src/ScatterChartPro/ScatterChartPro.tsx | 37 ++++++++++++------- .../useChartProZoom/useChartProZoom.ts | 8 +++- .../useChartProZoom/useChartProZoom.types.ts | 8 ++-- packages/x-charts/src/BarChart/BarChart.tsx | 3 ++ .../src/ChartContainer/ChartContainer.tsx | 3 ++ packages/x-charts/src/LineChart/LineChart.tsx | 3 ++ packages/x-charts/src/PieChart/PieChart.tsx | 3 ++ .../src/ScatterChart/ScatterChart.tsx | 3 ++ .../src/SparkLineChart/SparkLineChart.tsx | 3 ++ .../ChartDataProvider/ChartDataProvider.tsx | 1 + .../useChartDataProviderProps.ts | 2 + .../ChartProvider/ChartProvider.types.ts | 4 +- .../src/internals/store/useCharts.types.ts | 2 +- 30 files changed, 218 insertions(+), 113 deletions(-) diff --git a/docs/data/charts/zoom-and-pan/ZoomControlled.js b/docs/data/charts/zoom-and-pan/ZoomControlled.js index e7232b9c5bd7..9eaab87027c0 100644 --- a/docs/data/charts/zoom-and-pan/ZoomControlled.js +++ b/docs/data/charts/zoom-and-pan/ZoomControlled.js @@ -1,24 +1,28 @@ import * as React from 'react'; import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; - import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; +const initialZoomData = [ + { + axisId: 'my-x-axis', + start: 20, + end: 40, + }, +]; + export default function ZoomControlled() { - const [zoom, setZoom] = React.useState([ - { - axisId: 'my-x-axis', - start: 20, - end: 40, - }, - ]); + const apiRef = React.useRef(undefined); + + const [zoomData, setZoomData] = React.useState(initialZoomData); return ( setZoomData(newZoomData)} xAxis={[ { zoom: true, @@ -28,9 +32,12 @@ export default function ZoomControlled() { }, ]} /> +
{JSON.stringify(zoomData, null, 2)}
diff --git a/docs/data/charts/zoom-and-pan/ZoomControlled.tsx b/docs/data/charts/zoom-and-pan/ZoomControlled.tsx index 21c3f54f990f..859930b22090 100644 --- a/docs/data/charts/zoom-and-pan/ZoomControlled.tsx +++ b/docs/data/charts/zoom-and-pan/ZoomControlled.tsx @@ -1,24 +1,29 @@ import * as React from 'react'; import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; -import { ZoomData } from '@mui/x-charts-pro/models'; import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; +import { ChartPublicAPI, ZoomData } from '@mui/x-charts/internals'; +const initialZoomData: ZoomData[] = [ + { + axisId: 'my-x-axis', + start: 20, + end: 40, + }, +]; export default function ZoomControlled() { - const [zoom, setZoom] = React.useState([ - { - axisId: 'my-x-axis', - start: 20, - end: 40, - }, - ]); + const apiRef = React.useRef(undefined) as React.MutableRefObject< + ChartPublicAPI<[any]> | undefined + >; + const [zoomData, setZoomData] = React.useState(initialZoomData); return ( setZoomData(newZoomData)} xAxis={[ { zoom: true, @@ -28,9 +33,12 @@ export default function ZoomControlled() { }, ]} /> +
{JSON.stringify(zoomData, null, 2)}
diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index fd90bd6bafa5..b543a36a1a21 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -38,6 +38,12 @@ } }, "id": { "type": { "name": "string" } }, + "initialZoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + }, "layout": { "type": { "name": "enum", "description": "'horizontal'
| 'vertical'" }, "default": "'vertical'" @@ -114,12 +120,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "BarChartPro", diff --git a/docs/pages/x/api/charts/chart-container-pro.json b/docs/pages/x/api/charts/chart-container-pro.json index 3dfbc86a9076..60a59e684caa 100644 --- a/docs/pages/x/api/charts/chart-container-pro.json +++ b/docs/pages/x/api/charts/chart-container-pro.json @@ -14,6 +14,12 @@ } }, "id": { "type": { "name": "string" } }, + "initialZoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + }, "margin": { "type": { "name": "shape", @@ -54,12 +60,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "ChartContainerPro", diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index 3a6ef465ea85..379bfbfad092 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -36,6 +36,12 @@ } }, "id": { "type": { "name": "string" } }, + "initialZoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index ff5c974ca9d6..dacd8ba99ddb 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -39,6 +39,12 @@ } }, "id": { "type": { "name": "string" } }, + "initialZoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -107,12 +113,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "LineChartPro", diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index b507cc8239ed..6dcf6d5e6756 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -38,6 +38,12 @@ } }, "id": { "type": { "name": "string" } }, + "initialZoom": { + "type": { + "name": "arrayOf", + "description": "Array<{ axisId: number
| string, end: number, start: number }>" + } + }, "leftAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "yAxisIds[0] The id of the first provided axis" @@ -104,12 +110,6 @@ "name": "arrayOf", "description": "Array<{ colorMap?: { colors: Array<string>, type: 'ordinal', unknownColor?: string, values?: Array<Date
| number
| string> }
| { color: Array<string>
| func, max?: Date
| number, min?: Date
| number, type: 'continuous' }
| { colors: Array<string>, thresholds: Array<Date
| number>, type: 'piecewise' }, data?: array, dataKey?: string, id?: string, max?: number, min?: number }>" } - }, - "zoom": { - "type": { - "name": "arrayOf", - "description": "Array<{ axisId: number
| string, end: number, start: number }>" - } } }, "name": "ScatterChartPro", diff --git a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json index 94ab882e9674..a259f1f0e06e 100644 --- a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json +++ b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json @@ -30,6 +30,7 @@ "id": { "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." }, + "initialZoom": { "description": "The list of zoom data related to each axis." }, "layout": { "description": "The direction of the bar elements." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." @@ -83,8 +84,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json index ae1453986647..f9dad77f658e 100644 --- a/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json +++ b/docs/translations/api-docs/charts/chart-container-pro/chart-container-pro.json @@ -17,6 +17,7 @@ "id": { "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." }, + "initialZoom": { "description": "The list of zoom data related to each axis." }, "margin": { "description": "The margin between the SVG and the drawing area. It's used for leaving some space for extra information such as the x- and y-axis or legend. Accepts an object with the optional properties: top, bottom, left, and right." }, @@ -43,8 +44,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/heatmap/heatmap.json b/docs/translations/api-docs/charts/heatmap/heatmap.json index e74feb7819de..5cf0f1493f10 100644 --- a/docs/translations/api-docs/charts/heatmap/heatmap.json +++ b/docs/translations/api-docs/charts/heatmap/heatmap.json @@ -20,6 +20,7 @@ "id": { "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." }, + "initialZoom": { "description": "The list of zoom data related to each axis." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, diff --git a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json index 618f403e42ea..e6fd2e9e4695 100644 --- a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json +++ b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json @@ -32,6 +32,7 @@ "id": { "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." }, + "initialZoom": { "description": "The list of zoom data related to each axis." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -78,8 +79,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json index d62674842fb5..e31140e8e250 100644 --- a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json +++ b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json @@ -29,6 +29,7 @@ "id": { "description": "This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id." }, + "initialZoom": { "description": "The list of zoom data related to each axis." }, "leftAxis": { "description": "Indicate which axis to display the left of the charts. Can be a string (the id of the axis) or an object ChartsYAxisProps." }, @@ -77,8 +78,7 @@ "yAxis": { "description": "The configuration of the y-axes. If not provided, a default axis config is used. An array of AxisConfig objects." }, - "zAxis": { "description": "The configuration of the z-axes." }, - "zoom": { "description": "The list of zoom data related to each axis." } + "zAxis": { "description": "The configuration of the z-axes." } }, "classDescriptions": {} } diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 3a6f11ffd0ac..2c9bd3802210 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -62,7 +62,7 @@ BarChartPlotZoom.propTypes = { } as any; export interface BarChartProProps - extends BarChartProps, + extends Omit, Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** @@ -81,7 +81,7 @@ const BarChartPro = React.forwardRef(function BarChartPro( ref: React.Ref, ) { const props = useThemeProps({ props: inProps, name: 'MuiBarChartPro' }); - const { zoom, onZoomChange, ...other } = props; + const { initialZoom, onZoomChange, apiRef, ...other } = props; const { chartContainerProps, barPlotProps, @@ -99,7 +99,13 @@ const BarChartPro = React.forwardRef(function BarChartPro( const Tooltip = props.slots?.tooltip ?? ChartsTooltip; return ( - + {props.onAxisClick && } @@ -121,6 +127,11 @@ BarChartPro.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.shape({ + setZoomData: PropTypes.func.isRequired, + }), + }), /** * The configuration of axes highlight. * Default is set to 'band' in the bar direction. @@ -194,6 +205,16 @@ BarChartPro.propTypes = { * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, + /** + * The list of zoom data related to each axis. + */ + initialZoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), /** * The direction of the bar elements. * @default 'vertical' @@ -500,16 +521,6 @@ BarChartPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { BarChartPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 62b6d75f6632..99e5851b4a5e 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -71,6 +71,11 @@ ChartContainerPro.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.shape({ + setZoomData: PropTypes.func.isRequired, + }), + }), children: PropTypes.node, className: PropTypes.string, /** @@ -105,6 +110,16 @@ ChartContainerPro.propTypes = { * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, + /** + * The list of zoom data related to each axis. + */ + initialZoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), /** * The margin between the SVG and the drawing area. * It's used for leaving some space for extra information such as the x- and y-axis or legend. @@ -361,16 +376,6 @@ ChartContainerPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { ChartContainerPro }; diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index afc7c2179360..c5bb363ae5c7 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -27,16 +27,16 @@ export const useChartContainerProProps = , ref: React.Ref, ): UseChartContainerProPropsReturnValue => { - const { zoom, onZoomChange, plugins, ...baseProps } = props; + const { initialZoom, onZoomChange, plugins, apiRef, ...baseProps } = props; const chartDataProviderProProps: Pick< ChartDataProviderProps< [UseChartCartesianAxisSignature, UseChartProZoomSignature], TSeries >, - 'zoom' | 'onZoomChange' + 'initialZoom' | 'onZoomChange' > = { - zoom, + initialZoom, onZoomChange, }; @@ -49,6 +49,7 @@ export const useChartContainerProProps = >, diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index 60b4a70948b3..3ef229a81457 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -210,6 +210,11 @@ Heatmap.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.shape({ + setZoomData: PropTypes.func.isRequired, + }), + }), /** * Indicate which axis to display the bottom of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. @@ -250,6 +255,16 @@ Heatmap.propTypes = { * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, + /** + * The list of zoom data related to each axis. + */ + initialZoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index 01325289b49d..1deea3fb4d5f 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -130,7 +130,7 @@ MarkPlotZoom.propTypes = { } as any; export interface LineChartProProps - extends LineChartProps, + extends Omit, Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** @@ -148,7 +148,7 @@ const LineChartPro = React.forwardRef(function LineChartPro( ref: React.Ref, ) { const props = useThemeProps({ props: inProps, name: 'MuiLineChartPro' }); - const { zoom, onZoomChange, ...other } = props; + const { initialZoom, onZoomChange, apiRef, ...other } = props; const { chartContainerProps, axisClickHandlerProps, @@ -169,7 +169,13 @@ const LineChartPro = React.forwardRef(function LineChartPro( const Tooltip = props.slots?.tooltip ?? ChartsTooltip; return ( - + {props.onAxisClick && } @@ -197,6 +203,11 @@ LineChartPro.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.shape({ + setZoomData: PropTypes.func.isRequired, + }), + }), /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/highlighting/ highlighting docs} for more details. @@ -265,6 +276,16 @@ LineChartPro.propTypes = { * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, + /** + * The list of zoom data related to each axis. + */ + initialZoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -572,16 +593,6 @@ LineChartPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { LineChartPro }; diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index ea75001c4499..394029fabc4d 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -15,7 +15,7 @@ import { useScatterChartProps } from '@mui/x-charts/internals'; import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro'; export interface ScatterChartProProps - extends ScatterChartProps, + extends Omit, Omit, 'series' | 'plugins' | 'seriesConfig'> {} /** @@ -33,7 +33,7 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( ref: React.Ref, ) { const props = useThemeProps({ props: inProps, name: 'MuiScatterChartPro' }); - const { zoom, onZoomChange, ...other } = props; + const { initialZoom, onZoomChange, apiRef, ...other } = props; const { chartContainerProps, zAxisProps, @@ -50,7 +50,13 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( const Tooltip = props.slots?.tooltip ?? ChartsTooltip; return ( - + {!props.disableVoronoi && } @@ -74,6 +80,11 @@ ScatterChartPro.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.shape({ + setZoomData: PropTypes.func.isRequired, + }), + }), /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/highlighting/ highlighting docs} for more details. @@ -139,6 +150,16 @@ ScatterChartPro.propTypes = { * If you don't provide this prop. It falls back to a randomly generated id. */ id: PropTypes.string, + /** + * The list of zoom data related to each axis. + */ + initialZoom: PropTypes.arrayOf( + PropTypes.shape({ + axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, + end: PropTypes.number.isRequired, + start: PropTypes.number.isRequired, + }), + ), /** * Indicate which axis to display the left of the charts. * Can be a string (the id of the axis) or an object `ChartsYAxisProps`. @@ -438,16 +459,6 @@ ScatterChartPro.propTypes = { min: PropTypes.number, }), ), - /** - * The list of zoom data related to each axis. - */ - zoom: PropTypes.arrayOf( - PropTypes.shape({ - axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - end: PropTypes.number.isRequired, - start: PropTypes.number.isRequired, - }), - ), } as any; export { ScatterChartPro }; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts index 30a2582291ef..b94a2325ff69 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.ts @@ -351,6 +351,9 @@ export const useChartProZoom: ChartPlugin = ({ ]); return { + publicAPI: { + setZoomData: setZoomDataCallback, + }, instance: { setZoomData: setZoomDataCallback, }, @@ -358,7 +361,7 @@ export const useChartProZoom: ChartPlugin = ({ }; useChartProZoom.params = { - zoom: true, + initialZoom: true, onZoomChange: true, }; @@ -392,7 +395,8 @@ useChartProZoom.getInitialState = (params) => { return { zoom: { options: params.options, - zoomData: params.zoom === undefined ? initializeZoomData(params.options) : params.zoom, + zoomData: + params.initialZoom === undefined ? initializeZoomData(params.options) : params.initialZoom, isInteracting: false, }, }; diff --git a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts index f90ad8dfce8d..d80273d7a7e8 100644 --- a/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts +++ b/packages/x-charts-pro/src/internals/plugins/useChartProZoom/useChartProZoom.types.ts @@ -12,7 +12,7 @@ export interface UseChartProZoomParameters { /** * The list of zoom data related to each axis. */ - zoom?: ZoomData[]; + initialZoom?: ZoomData[]; /** * Callback fired when the zoom has changed. * @@ -47,7 +47,7 @@ export interface UseChartProZoomState { }; } -export interface UseChartProZoomInstance { +export interface UseChartProZoomPublicApi { /** * Set the zoom data state. * @param {ZoomData[] | ((prev: ZoomData[]) => ZoomData[])} value The new value. Can either be the new zoom data, or an updater function. @@ -56,11 +56,13 @@ export interface UseChartProZoomInstance { setZoomData: (value: ZoomData[] | ((prev: ZoomData[]) => ZoomData[])) => void; } +export interface UseChartProZoomInstance extends UseChartProZoomPublicApi {} + export type UseChartProZoomSignature = ChartPluginSignature<{ params: UseChartProZoomParameters; defaultizedParams: UseChartProZoomDefaultizedParameters; state: UseChartProZoomState; + publicAPI: UseChartProZoomPublicApi; instance: UseChartProZoomInstance; - modelNames: 'zoom'; dependencies: [UseChartSeriesSignature, UseChartCartesianAxisSignature]; }>; diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index d42550a7ff06..4efd8cb9e642 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -138,6 +138,9 @@ BarChart.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), /** * The configuration of axes highlight. * Default is set to 'band' in the bar direction. diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 9f8d02586f84..83b232dd75aa 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -63,6 +63,9 @@ ChartContainer.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), children: PropTypes.node, className: PropTypes.string, /** diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 9f1ddbd4ffb7..0d7482f53b6c 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -176,6 +176,9 @@ LineChart.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/highlighting/ highlighting docs} for more details. diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index ecf9f2f3cacc..64c8f2d80e3c 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -140,6 +140,9 @@ PieChart.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), children: PropTypes.node, className: PropTypes.string, /** diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index 4b5cd53b9358..009545bac3b7 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -147,6 +147,9 @@ ScatterChart.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/highlighting/ highlighting docs} for more details. diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index 333b81003bc0..0907d9813d7e 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -229,6 +229,9 @@ SparkLineChart.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.shape({ + current: PropTypes.object, + }), /** * Set to `true` to fill spark line area. * Has no effect if plotType='bar'. diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 438977b18d82..faee4181d2a0 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -82,6 +82,7 @@ ChartDataProvider.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + apiRef: PropTypes.any, children: PropTypes.node, /** * Color palette used to colorize multiple series. diff --git a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts index de0a33c64df3..ab4b65e871ae 100644 --- a/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts +++ b/packages/x-charts/src/context/ChartDataProvider/useChartDataProviderProps.ts @@ -16,6 +16,7 @@ export const useChartDataProviderProps = < props: ChartDataProviderProps, ) => { const { + apiRef, width, height, series, @@ -38,6 +39,7 @@ export const useChartDataProviderProps = < plugins, seriesConfig, pluginParams: { + apiRef, width, height, margin, diff --git a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts index 82da0aa004e0..ad550c950c40 100644 --- a/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts +++ b/packages/x-charts/src/context/ChartProvider/ChartProvider.types.ts @@ -9,6 +9,7 @@ import { import { ChartStore } from '../../internals/plugins/utils/ChartStore'; import { ChartCorePluginSignatures } from '../../internals/plugins/corePlugins'; import { ChartSeriesConfig } from '../../internals/plugins/models/seriesConfig'; +import { UseChartBaseProps } from '../../internals/store/useCharts.types'; import { ChartSeriesType } from '../../models/seriesType/config'; export type ChartContextValue< @@ -41,7 +42,8 @@ export interface ChartProviderProps< * Array of plugins used to add features to the chart. */ plugins?: ConvertSignaturesIntoPlugins; - pluginParams?: MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; + pluginParams?: UseChartBaseProps & + MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'params'>; /** * The configuration helpers used to compute attributes according to the serries type. * @ignore Unstable props for internal usage. diff --git a/packages/x-charts/src/internals/store/useCharts.types.ts b/packages/x-charts/src/internals/store/useCharts.types.ts index 1b229c8470ae..b9e517d713da 100644 --- a/packages/x-charts/src/internals/store/useCharts.types.ts +++ b/packages/x-charts/src/internals/store/useCharts.types.ts @@ -2,5 +2,5 @@ import * as React from 'react'; import { ChartAnyPluginSignature, ChartPublicAPI } from '../plugins/models'; export interface UseChartBaseProps { - apiRef: React.MutableRefObject | undefined> | undefined; + apiRef?: React.MutableRefObject | undefined> | undefined; }