Skip to content

Commit

Permalink
[charts] Take responsive container from data grid (#9497)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfauquette authored Jun 28, 2023
1 parent 575be07 commit 7f90a1b
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 35 deletions.
1 change: 0 additions & 1 deletion packages/x-charts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
},
"dependencies": {
"@babel/runtime": "^7.22.5",
"@juggle/resize-observer": "^3.4.0",
"@types/d3-color": "^3.1.0",
"@types/d3-scale": "^4.0.3",
"@types/d3-shape": "^3.1.1",
Expand Down
17 changes: 9 additions & 8 deletions packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export const ChartsTooltipRow = styled('tr', {
name: 'MuiChartsTooltip',
slot: 'Row',
})(({ theme }) => ({
'&:first-child td': {
'tr:first-of-type& td': {
paddingTop: theme.spacing(1),
},
'&:last-child td': {
'tr:last-of-type& td': {
paddingBottom: theme.spacing(1),
},
}));
Expand All @@ -37,19 +37,20 @@ export const ChartsTooltipCell = styled('td', {
verticalAlign: 'middle',
color: theme.palette.text.secondary,

'&:first-child': {
paddingLeft: theme.spacing(2),
},
'&:last-child': {
paddingRight: theme.spacing(2),
},
[`&.${tooltipClasses.labelCell}`]: {
paddingLeft: theme.spacing(1),
},
[`&.${tooltipClasses.valueCell}`]: {
paddingLeft: theme.spacing(4),
color: theme.palette.text.primary,
},

'td:first-of-type&': {
paddingLeft: theme.spacing(2),
},
'td:last-of-type&': {
paddingRight: theme.spacing(2),
},
}));

export const ChartsTooltipMark = styled(Box, {
Expand Down
110 changes: 89 additions & 21 deletions packages/x-charts/src/ResponsiveChartContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,121 @@
import * as React from 'react';
import { ResizeObserver } from '@juggle/resize-observer';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
import ownerWindow from '@mui/utils/ownerWindow';
import { styled } from '@mui/material/styles';
import { ChartContainer, ChartContainerProps } from '../ChartContainer';
import { MakeOptional } from '../models/helpers';

const useChartDimensions = (
inWidth?: number,
inHeight?: number,
): [React.RefObject<HTMLDivElement>, number, number] => {
const ref = React.useRef<HTMLDivElement>(null);
const rootRef = React.useRef<HTMLDivElement>(null);
const displayError = React.useRef<boolean>(false);

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 = parseFloat(computedStyle.height) || 0;
const newWidth = parseFloat(computedStyle.width) || 0;

setWidth(newWidth);
setHeight(newHeight);
}, []);

React.useEffect(() => {
const element = ref.current;
if (element === null || (inHeight !== undefined && inWidth !== undefined)) {
// Ensure the error detection occurs after the first rendering.
displayError.current = true;
}, []);

useEnhancedEffect(() => {
if (inWidth !== undefined && inHeight !== undefined) {
return () => {};
}
computeSize();

const resizeObserver = new ResizeObserver((entries) => {
if (Array.isArray(entries) && entries.length) {
const entry = entries[0];
if (inWidth === undefined) {
setWidth(entry.contentRect.width);
}
if (inHeight === undefined) {
setHeight(entry.contentRect.height);
}
}
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 = window.requestAnimationFrame(() => {
computeSize();
});
});
resizeObserver.observe(element);

return () => resizeObserver.disconnect();
}, [height, inHeight, inWidth, width]);
if (elementToObserve) {
observer.observe(elementToObserve);
}

return () => {
if (animationFrame) {
window.cancelAnimationFrame(animationFrame);
}

if (elementToObserve) {
observer.unobserve(elementToObserve);
}
};
}, [computeSize, inHeight, inWidth]);

return [ref, inWidth ?? width, inHeight ?? height];
if (process.env.NODE_ENV !== 'production') {
if (displayError.current && inWidth === undefined && width === 0) {
console.error(
`MUI: Charts does not have \`width\` prop, and its container has no \`width\` defined.`,
);
displayError.current = false;
}
if (displayError.current && inHeight === undefined && height === 0) {
console.error(
`MUI: Charts does not have \`height\` prop, and its container has no \`height\` defined.`,
);
displayError.current = false;
}
}

return [rootRef, inWidth ?? width, inHeight ?? height];
};

export type ResponsiveChartContainerProps = MakeOptional<ChartContainerProps, 'width' | 'height'>;

const ResizableContainer = styled('div', {
name: 'MuiResponsiveChart',
slot: 'Container',
})<{ ownerState: Pick<ResponsiveChartContainerProps, 'width' | 'height'> }>(({ ownerState }) => ({
width: ownerState.width ?? '100%',
height: ownerState.height ?? '100%',
display: 'flex',
position: 'relative',
flexGrow: 1,
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
overflow: 'hidden',
}));

export function ResponsiveChartContainer(props: ResponsiveChartContainerProps) {
const [containerRef, width, height] = useChartDimensions(props.width, props.height);

return (
<div
<ResizableContainer
ref={containerRef}
style={{ width: props.width ?? '100%', height: props.height ?? '100%', padding: 0 }}
ownerState={{ width: props.width, height: props.height }}
>
<ChartContainer {...props} width={width} height={height} />
</div>
</ResizableContainer>
);
}
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1685,11 +1685,6 @@
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"

"@juggle/resize-observer@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==

"@lerna/child-process@6.6.2":
version "6.6.2"
resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-6.6.2.tgz#5d803c8dee81a4e013dc428292e77b365cba876c"
Expand Down

0 comments on commit 7f90a1b

Please sign in to comment.