Skip to content

Commit

Permalink
[charts] Decouple ChartDataProvider and ChartsSurface (#15375)
Browse files Browse the repository at this point in the history
  • Loading branch information
JCQuintas authored Nov 18, 2024
1 parent 69e7783 commit d172745
Show file tree
Hide file tree
Showing 40 changed files with 339 additions and 362 deletions.
6 changes: 1 addition & 5 deletions docs/pages/x/api/charts/charts-surface.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
{
"props": {
"height": { "type": { "name": "number" }, "required": true },
"width": { "type": { "name": "number" }, "required": true },
"disableAxisListener": { "type": { "name": "bool" }, "default": "false" }
},
"props": { "disableAxisListener": { "type": { "name": "bool" }, "default": "false" } },
"name": "ChartsSurface",
"imports": [
"import { ChartsSurface } from '@mui/x-charts/ChartsSurface';",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
"propDescriptions": {
"disableAxisListener": {
"description": "If <code>true</code>, 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." },
"width": { "description": "The width of the chart in px." }
}
},
"classDescriptions": {}
}
6 changes: 0 additions & 6 deletions packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,6 @@ BarChartPro.propTypes = {
* @default null
*/
topAxis: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
19 changes: 8 additions & 11 deletions packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {} from '../typeOverloads';
import { Watermark } from '@mui/x-license/Watermark';
import { ChartContainerProps } from '@mui/x-charts/ChartContainer';
import { ResizableContainer } from '@mui/x-charts/internals';
import { ChartsSurface } from '@mui/x-charts';
import { getReleaseInfo } from '../internals/utils/releaseInfo';
import { ChartDataProviderPro } from '../context/ChartDataProviderPro';
import { ZoomProps } from '../context/ZoomProvider';
Expand All @@ -18,14 +19,16 @@ const ChartContainerPro = React.forwardRef(function ChartContainerPro(
props: ChartContainerProProps,
ref: React.Ref<SVGSVGElement>,
) {
const { chartDataProviderProProps, resizableChartContainerProps, hasIntrinsicSize } =
const { chartDataProviderProProps, children, resizableContainerProps, chartsSurfaceProps } =
useChartContainerProProps(props, ref);

return (
<ResizableContainer {...resizableChartContainerProps}>
{hasIntrinsicSize ? <ChartDataProviderPro {...chartDataProviderProProps} /> : null}
<Watermark packageName="x-charts-pro" releaseInfo={releaseInfo} />
</ResizableContainer>
<ChartDataProviderPro {...chartDataProviderProProps}>
<ResizableContainer {...resizableContainerProps}>
<ChartsSurface {...chartsSurfaceProps}>{children}</ChartsSurface>
<Watermark packageName="x-charts-pro" releaseInfo={releaseInfo} />
</ResizableContainer>
</ChartDataProviderPro>
);
});

Expand Down Expand Up @@ -119,12 +122,6 @@ ChartContainerPro.propTypes = {
PropTypes.object,
]),
title: PropTypes.string,
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';
import { useChartContainerProps, UseChartContainerPropsReturnValue } from '@mui/x-charts/internals';
import * as React from 'react';
import type { ChartDataProviderProProps } from '../context/ChartDataProviderPro';
import type { ChartContainerProProps } from './ChartContainerPro';

Expand All @@ -13,23 +14,24 @@ export type UseChartContainerProPropsReturnValue = Omit<
export const useChartContainerProProps = (
props: ChartContainerProProps,
ref: React.Ref<SVGSVGElement>,
) => {
): UseChartContainerProPropsReturnValue => {
const { zoom, onZoomChange, ...baseProps } = props;

const chartDataProviderProProps: Pick<ChartDataProviderProProps, 'zoom' | 'onZoomChange'> = {
zoom,
onZoomChange,
};

const { chartDataProviderProps, resizableChartContainerProps, hasIntrinsicSize } =
const { chartDataProviderProps, chartsSurfaceProps, resizableContainerProps, children } =
useChartContainerProps(baseProps, ref);

return {
chartDataProviderProProps: {
...chartDataProviderProps,
...chartDataProviderProProps,
},
resizableChartContainerProps,
hasIntrinsicSize,
resizableContainerProps,
chartsSurfaceProps,
children,
};
};
6 changes: 0 additions & 6 deletions packages/x-charts-pro/src/Heatmap/Heatmap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,6 @@ Heatmap.propTypes = {
* @default null
*/
topAxis: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
6 changes: 0 additions & 6 deletions packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,6 @@ LineChartPro.propTypes = {
* @default null
*/
topAxis: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
6 changes: 0 additions & 6 deletions packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,12 +236,6 @@ ScatterChartPro.propTypes = {
* @default null
*/
topAxis: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* Defines the maximal distance between a scatter point and the pointer that triggers the interaction.
* If `undefined`, the radius is assumed to be infinite.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import {
ChartDataProviderProps,
ChartsAxesGradients,
DrawingAreaProvider,
InteractionProvider,
PluginProvider,
SeriesProvider,
AnimationProvider,
SvgRefProvider,
SizeProvider,
} from '@mui/x-charts/internals';
import { ChartsSurface } from '@mui/x-charts/ChartsSurface';
import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context';
import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier';
import { getReleaseInfo } from '../../internals/utils/releaseInfo';
Expand All @@ -23,29 +22,25 @@ const releaseInfo = getReleaseInfo();

export interface ChartDataProviderProProps extends ChartDataProviderProps, ZoomProps {}

const ChartDataProviderPro = React.forwardRef(function ChartDataProviderPro(
props: ChartDataProviderProProps,
ref: React.Ref<SVGSVGElement>,
) {
function ChartDataProviderPro(props: ChartDataProviderProProps) {
const {
zoomProviderProps,
drawingAreaProviderProps,
seriesProviderProps,
zAxisContextProps,
highlightedProviderProps,
cartesianProviderProps,
chartsSurfaceProps,
sizeProviderProps,
pluginProviderProps,
animationProviderProps,
svgRefProviderProps,
children,
} = useChartContainerProProps(props, ref);
} = useChartContainerProProps(props);

useLicenseVerifier('x-charts-pro', releaseInfo);

return (
<DrawingAreaProvider {...drawingAreaProviderProps}>
<SvgRefProvider {...svgRefProviderProps}>
<SizeProvider {...sizeProviderProps}>
<DrawingAreaProvider {...drawingAreaProviderProps}>
<AnimationProvider {...animationProviderProps}>
<PluginProvider {...pluginProviderProps}>
<ZoomProvider {...zoomProviderProps}>
Expand All @@ -54,10 +49,7 @@ const ChartDataProviderPro = React.forwardRef(function ChartDataProviderPro(
<ZAxisContextProvider {...zAxisContextProps}>
<InteractionProvider>
<HighlightedProvider {...highlightedProviderProps}>
<ChartsSurface {...chartsSurfaceProps}>
<ChartsAxesGradients />
{children}
</ChartsSurface>
<SvgRefProvider>{children}</SvgRefProvider>
</HighlightedProvider>
</InteractionProvider>
</ZAxisContextProvider>
Expand All @@ -66,10 +58,10 @@ const ChartDataProviderPro = React.forwardRef(function ChartDataProviderPro(
</ZoomProvider>
</PluginProvider>
</AnimationProvider>
</SvgRefProvider>
</DrawingAreaProvider>
</DrawingAreaProvider>
</SizeProvider>
);
});
}

ChartDataProviderPro.propTypes = {
// ----------------------------- Warning --------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { useChartDataProviderProps } from '@mui/x-charts/internals';
import { ZoomProviderProps } from '../ZoomProvider';
import type { ChartDataProviderProProps } from './ChartDataProviderPro';

export const useChartContainerProProps = (
props: ChartDataProviderProProps,
ref: React.Ref<SVGSVGElement>,
) => {
export const useChartContainerProProps = (props: ChartDataProviderProProps) => {
const { zoom, onZoomChange, ...baseProps } = props;

const {
Expand All @@ -16,13 +13,12 @@ export const useChartContainerProProps = (
cartesianProviderProps,
zAxisContextProps,
highlightedProviderProps,
chartsSurfaceProps,
sizeProviderProps,
pluginProviderProps,
animationProviderProps,
svgRefProviderProps,
xAxis,
yAxis,
} = useChartDataProviderProps(baseProps, ref);
} = useChartDataProviderProps(baseProps);

const zoomProviderProps: Omit<ZoomProviderProps, 'children'> = {
zoom,
Expand All @@ -40,8 +36,7 @@ export const useChartContainerProProps = (
cartesianProviderProps,
zAxisContextProps,
highlightedProviderProps,
chartsSurfaceProps,
sizeProviderProps,
animationProviderProps,
svgRefProviderProps,
};
};
6 changes: 0 additions & 6 deletions packages/x-charts/src/BarChart/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,6 @@ BarChart.propTypes = {
* @default null
*/
topAxis: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
38 changes: 8 additions & 30 deletions packages/x-charts/src/ChartContainer/ChartContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,23 @@ import PropTypes from 'prop-types';
import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider';
import { ResizableContainer } from './ResizableContainer';
import { useChartContainerProps } from './useChartContainerProps';
import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface';

export interface ChartContainerProps extends Omit<ChartDataProviderProps, 'width' | 'height'> {
/**
* 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 chart will try to wait for the parent container to resolve its size
* before it renders for the first time.
*
* This can be useful in some scenarios where the chart appear to grow after
* the first render, like when used inside a grid.
*
* @default false
*/
resolveSizeBeforeRender?: boolean;
}
export interface ChartContainerProps extends ChartDataProviderProps, ChartsSurfaceProps {}

const ChartContainer = React.forwardRef(function ChartContainer(
props: ChartContainerProps,
ref: React.Ref<SVGSVGElement>,
) {
const { hasIntrinsicSize, chartDataProviderProps, resizableChartContainerProps } =
const { chartDataProviderProps, children, resizableContainerProps, chartsSurfaceProps } =
useChartContainerProps(props, ref);

return (
<ResizableContainer {...resizableChartContainerProps}>
{hasIntrinsicSize ? <ChartDataProvider {...chartDataProviderProps} /> : null}
</ResizableContainer>
<ChartDataProvider {...chartDataProviderProps}>
<ResizableContainer {...resizableContainerProps}>
<ChartsSurface {...chartsSurfaceProps}>{children}</ChartsSurface>
</ResizableContainer>
</ChartDataProvider>
);
});

Expand Down Expand Up @@ -124,12 +108,6 @@ ChartContainer.propTypes = {
PropTypes.object,
]),
title: PropTypes.string,
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px. If not defined, it takes the width of the parent element.
*/
Expand Down
38 changes: 35 additions & 3 deletions packages/x-charts/src/ChartContainer/ResizableContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import type { ChartContainerProps } from './ChartContainer';
import { useSize } from '../context/SizeProvider';
import type { SizeContextState } from '../context/SizeProvider';

/**
* Wrapping div that take the shape of its parent.
*
* @ignore - do not document.
*/
export const ResizableContainer = styled('div', {
export const ResizableContainerRoot = styled('div', {
name: 'MuiResponsiveChart',
slot: 'Container',
})<{ ownerState: Pick<ChartContainerProps, 'width' | 'height'> }>(({ ownerState }) => ({
})<{ ownerState: Partial<Pick<SizeContextState, 'width' | 'height'>> }>(({ ownerState }) => ({
width: ownerState.width ?? '100%',
height: ownerState.height ?? '100%',
display: 'flex',
Expand All @@ -24,3 +27,32 @@ export const ResizableContainer = styled('div', {
height: '100%',
},
}));

/**
* Wrapping div that take the shape of its parent.
*
* @ignore - do not document.
*/
function ResizableContainer(props: { children: React.ReactNode }) {
const { inHeight, inWidth, hasIntrinsicSize, containerRef } = useSize();

return (
<ResizableContainerRoot
{...props}
ownerState={{ width: inWidth, height: inHeight }}
ref={containerRef}
>
{hasIntrinsicSize && props.children}
</ResizableContainerRoot>
);
}

ResizableContainer.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,
} as any;

export { ResizableContainer };
Loading

0 comments on commit d172745

Please sign in to comment.