diff --git a/packages/x-charts/package.json b/packages/x-charts/package.json index d063c8c392a3..a1f2bd2de639 100644 --- a/packages/x-charts/package.json +++ b/packages/x-charts/package.json @@ -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", diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx index 00d71b554c86..d65245fc417c 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltipTable.tsx @@ -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), }, })); @@ -37,12 +37,6 @@ 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), }, @@ -50,6 +44,13 @@ export const ChartsTooltipCell = styled('td', { 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, { diff --git a/packages/x-charts/src/ResponsiveChartContainer/index.tsx b/packages/x-charts/src/ResponsiveChartContainer/index.tsx index 9a32f6c76589..32f1d1505182 100644 --- a/packages/x-charts/src/ResponsiveChartContainer/index.tsx +++ b/packages/x-charts/src/ResponsiveChartContainer/index.tsx @@ -1,5 +1,7 @@ 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'; @@ -7,47 +9,113 @@ const useChartDimensions = ( inWidth?: number, inHeight?: number, ): [React.RefObject, number, number] => { - const ref = React.useRef(null); + const rootRef = React.useRef(null); + const displayError = React.useRef(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; +const ResizableContainer = styled('div', { + name: 'MuiResponsiveChart', + slot: 'Container', +})<{ ownerState: Pick }>(({ 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 ( -
-
+ ); } diff --git a/yarn.lock b/yarn.lock index 31edaef3ae8b..8617775003ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"