From 0c9634bfe957522ed506a5b4d81ac81601c3d8b3 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 20 Nov 2024 15:43:24 +0100 Subject: [PATCH 01/24] direct svg --- .../ChartContainerPro/ChartContainerPro.tsx | 13 ++--- .../useChartContainerProProps.ts | 7 ++- .../src/ChartContainer/ChartContainer.tsx | 11 ++-- .../src/ChartContainer/ResizableContainer.tsx | 58 ------------------- .../ChartContainer/useChartContainerProps.ts | 5 +- .../src/ChartsSurface/ChartsSurface.tsx | 20 +++++-- packages/x-charts/src/internals/index.ts | 2 - 7 files changed, 31 insertions(+), 85 deletions(-) delete mode 100644 packages/x-charts/src/ChartContainer/ResizableContainer.tsx diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 4b77a752926a..8d546e83b846 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; 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'; @@ -19,15 +18,15 @@ const ChartContainerPro = React.forwardRef(function ChartContainerPro( props: ChartContainerProProps, ref: React.Ref, ) { - const { chartDataProviderProProps, children, resizableContainerProps, chartsSurfaceProps } = - useChartContainerProProps(props, ref); + const { chartDataProviderProProps, children, chartsSurfaceProps } = useChartContainerProProps( + props, + ref, + ); return ( - - {children} - - + {children} + ); }); diff --git a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts index aac56a291a32..b8b898c95ef3 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/useChartContainerProProps.ts @@ -22,15 +22,16 @@ export const useChartContainerProProps = ( onZoomChange, }; - const { chartDataProviderProps, chartsSurfaceProps, resizableContainerProps, children } = - useChartContainerProps(baseProps, ref); + const { chartDataProviderProps, chartsSurfaceProps, children } = useChartContainerProps( + baseProps, + ref, + ); return { chartDataProviderProProps: { ...chartDataProviderProps, ...chartDataProviderProProps, }, - resizableContainerProps, chartsSurfaceProps, children, }; diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index 64c82944b3d9..df2caef81db2 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { ChartDataProvider, ChartDataProviderProps } from '../context/ChartDataProvider'; -import { ResizableContainer } from './ResizableContainer'; import { useChartContainerProps } from './useChartContainerProps'; import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; @@ -12,14 +11,14 @@ const ChartContainer = React.forwardRef(function ChartContainer( props: ChartContainerProps, ref: React.Ref, ) { - const { chartDataProviderProps, children, resizableContainerProps, chartsSurfaceProps } = - useChartContainerProps(props, ref); + const { chartDataProviderProps, children, chartsSurfaceProps } = useChartContainerProps( + props, + ref, + ); return ( - - {children} - + {children} ); }); diff --git a/packages/x-charts/src/ChartContainer/ResizableContainer.tsx b/packages/x-charts/src/ChartContainer/ResizableContainer.tsx deleted file mode 100644 index e5c0f57d42a0..000000000000 --- a/packages/x-charts/src/ChartContainer/ResizableContainer.tsx +++ /dev/null @@ -1,58 +0,0 @@ -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'; - -/** - * Wrapping div that take the shape of its parent. - * - * @ignore - do not document. - */ -export const ResizableContainerRoot = styled('div', { - name: 'MuiResponsiveChart', - slot: 'Container', -})<{ ownerState: Partial> }>(({ ownerState }) => ({ - width: ownerState.width ?? '100%', - height: ownerState.height ?? '100%', - display: 'flex', - position: 'relative', - flexGrow: 1, - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - overflow: 'hidden', - '&>svg': { - width: '100%', - height: '100%', - }, -})); - -/** - * Wrapping div that take the shape of its parent. - * - * @ignore - do not document. - */ -function ResizableContainer(props: { children: React.ReactNode }) { - const { inHeight, inWidth, containerRef } = useSize(); - - return ( - - {props.children} - - ); -} - -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 }; diff --git a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts index 8fa2a647f20d..395a2ff1bc95 100644 --- a/packages/x-charts/src/ChartContainer/useChartContainerProps.ts +++ b/packages/x-charts/src/ChartContainer/useChartContainerProps.ts @@ -7,7 +7,6 @@ import type { ChartContainerProps } from './ChartContainer'; export type UseChartContainerPropsReturnValue = { chartDataProviderProps: ChartDataProviderProps; chartsSurfaceProps: ChartsSurfaceProps & { ref: React.Ref }; - resizableContainerProps: any; children: React.ReactNode; }; @@ -37,14 +36,13 @@ export const useChartContainerProps = ( ...other } = props; - const resizableContainerProps = other; - const chartsSurfaceProps: ChartsSurfaceProps & { ref: React.Ref } = { title, desc, sx, disableAxisListener, ref, + ...other, }; const chartDataProviderProps: ChartDataProviderProps = { @@ -65,7 +63,6 @@ export const useChartContainerProps = ( return { chartDataProviderProps, - resizableContainerProps, chartsSurfaceProps, children, }; diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index c8ffec6abace..3e17bd99572a 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -6,8 +6,8 @@ import useForkRef from '@mui/utils/useForkRef'; import { useAxisEvents } from '../hooks/useAxisEvents'; import { ChartsAxesGradients } from '../internals/components/ChartsAxesGradients'; import { useDrawingArea } from '../hooks'; -import { useSurfaceRef } from '../context/SvgRefProvider'; import { useSize } from '../context/SizeProvider'; +import type { SizeContextState } from '../context/SizeProvider'; export interface ChartsSurfaceProps { className?: string; @@ -26,7 +26,17 @@ export interface ChartsSurfaceProps { const ChartsSurfaceStyles = styled('svg', { name: 'MuiChartsSurface', slot: 'Root', -})(() => ({ +})<{ ownerState: Partial> }>(({ ownerState }) => ({ + width: ownerState.width ?? '100%', + height: ownerState.height ?? '100%', + display: 'flex', + position: 'relative', + flexGrow: 1, + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + // This prevents default touch actions when using the svg on mobile devices. // For example, prevent page scroll & zoom. touchAction: 'none', @@ -37,9 +47,8 @@ const ChartsSurface = React.forwardRef(functi ref: React.Ref, ) { const { width, height, left, right, top, bottom } = useDrawingArea(); - const { hasIntrinsicSize } = useSize(); - const surfaceRef = useSurfaceRef(); - const handleRef = useForkRef(surfaceRef, ref); + const { hasIntrinsicSize, containerRef, inHeight, inWidth } = useSize(); + const handleRef = useForkRef(containerRef as any, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); const { children, disableAxisListener = false, className, title, desc, ...other } = themeProps; @@ -58,6 +67,7 @@ const ChartsSurface = React.forwardRef(functi return ( Date: Wed, 20 Nov 2024 16:04:05 +0100 Subject: [PATCH 02/24] fix svgref --- packages/x-charts/src/ChartsSurface/ChartsSurface.tsx | 2 +- packages/x-charts/src/context/SizeProvider/Size.types.ts | 2 +- packages/x-charts/src/hooks/useSvgRef.ts | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 3e17bd99572a..5800ab73d71a 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -48,7 +48,7 @@ const ChartsSurface = React.forwardRef(functi ) { const { width, height, left, right, top, bottom } = useDrawingArea(); const { hasIntrinsicSize, containerRef, inHeight, inWidth } = useSize(); - const handleRef = useForkRef(containerRef as any, ref); + const handleRef = useForkRef(containerRef, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); const { children, disableAxisListener = false, className, title, desc, ...other } = themeProps; diff --git a/packages/x-charts/src/context/SizeProvider/Size.types.ts b/packages/x-charts/src/context/SizeProvider/Size.types.ts index 811e5dcd498d..e188d939eb10 100644 --- a/packages/x-charts/src/context/SizeProvider/Size.types.ts +++ b/packages/x-charts/src/context/SizeProvider/Size.types.ts @@ -16,7 +16,7 @@ export interface SizeContextState extends Required; + containerRef: React.RefObject; /** * If the chart has a defined size. */ diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index ef1e3fe842ac..f7911bd38e28 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; -import { SvgRefContext } from '../context/SvgRefProvider'; +import { SizeContext } from '../context/SizeProvider'; -export function useSvgRef(): React.MutableRefObject { - const { isInitialized, data } = React.useContext(SvgRefContext); +export function useSvgRef(): React.Ref { + const { isInitialized, data } = React.useContext(SizeContext); if (!isInitialized) { throw new Error( @@ -14,5 +14,5 @@ export function useSvgRef(): React.MutableRefObject { ); } - return data.svgRef as React.MutableRefObject; + return data.containerRef; } From 4cf057d0350912ee752da7afb6f9baa6233d1b02 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 20 Nov 2024 16:14:09 +0100 Subject: [PATCH 03/24] Revert "fix svgref" This reverts commit 468c05e521111a79d42fd51cfc7a4abe7c7fb4d8. --- packages/x-charts/src/ChartsSurface/ChartsSurface.tsx | 2 +- packages/x-charts/src/context/SizeProvider/Size.types.ts | 2 +- packages/x-charts/src/hooks/useSvgRef.ts | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 5800ab73d71a..3e17bd99572a 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -48,7 +48,7 @@ const ChartsSurface = React.forwardRef(functi ) { const { width, height, left, right, top, bottom } = useDrawingArea(); const { hasIntrinsicSize, containerRef, inHeight, inWidth } = useSize(); - const handleRef = useForkRef(containerRef, ref); + const handleRef = useForkRef(containerRef as any, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); const { children, disableAxisListener = false, className, title, desc, ...other } = themeProps; diff --git a/packages/x-charts/src/context/SizeProvider/Size.types.ts b/packages/x-charts/src/context/SizeProvider/Size.types.ts index e188d939eb10..811e5dcd498d 100644 --- a/packages/x-charts/src/context/SizeProvider/Size.types.ts +++ b/packages/x-charts/src/context/SizeProvider/Size.types.ts @@ -16,7 +16,7 @@ export interface SizeContextState extends Required; + containerRef: React.RefObject; /** * If the chart has a defined size. */ diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index f7911bd38e28..ef1e3fe842ac 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; -import { SizeContext } from '../context/SizeProvider'; +import { SvgRefContext } from '../context/SvgRefProvider'; -export function useSvgRef(): React.Ref { - const { isInitialized, data } = React.useContext(SizeContext); +export function useSvgRef(): React.MutableRefObject { + const { isInitialized, data } = React.useContext(SvgRefContext); if (!isInitialized) { throw new Error( @@ -14,5 +14,5 @@ export function useSvgRef(): React.Ref { ); } - return data.containerRef; + return data.svgRef as React.MutableRefObject; } From db2de3c45a4cdd3bb01ed909e1ba787e97ecc32c Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Thu, 21 Nov 2024 13:22:12 +0100 Subject: [PATCH 04/24] Remove SvgRefProvider --- .../ChartDataProviderPro.tsx | 3 +- .../src/ChartsSurface/ChartsSurface.test.tsx | 15 ++--- .../src/ChartsSurface/ChartsSurface.tsx | 2 +- .../ChartsVoronoiHandler.tsx | 15 +++-- .../x-charts/src/Gauge/GaugeContainer.tsx | 65 +++++++++---------- .../ChartDataProvider/ChartDataProvider.tsx | 5 +- .../src/context/SizeProvider/Size.types.ts | 4 +- .../src/context/SizeProvider/SizeContext.ts | 2 +- .../useChartContainerDimensions.ts | 4 +- .../context/SvgRefProvider/SvgRef.types.ts | 10 --- .../context/SvgRefProvider/SvgRefContext.tsx | 16 ----- .../context/SvgRefProvider/SvgRefProvider.tsx | 18 ----- .../src/context/SvgRefProvider/index.ts | 4 -- .../context/SvgRefProvider/useSurfaceRef.ts | 18 ----- .../x-charts/src/hooks/useSvgRef.test.tsx | 19 ++---- packages/x-charts/src/hooks/useSvgRef.ts | 8 +-- packages/x-charts/src/internals/index.ts | 1 - 17 files changed, 63 insertions(+), 146 deletions(-) delete mode 100644 packages/x-charts/src/context/SvgRefProvider/SvgRef.types.ts delete mode 100644 packages/x-charts/src/context/SvgRefProvider/SvgRefContext.tsx delete mode 100644 packages/x-charts/src/context/SvgRefProvider/SvgRefProvider.tsx delete mode 100644 packages/x-charts/src/context/SvgRefProvider/index.ts delete mode 100644 packages/x-charts/src/context/SvgRefProvider/useSurfaceRef.ts diff --git a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx index 91ca02d3f8cd..186fae9656ba 100644 --- a/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx +++ b/packages/x-charts-pro/src/context/ChartDataProviderPro/ChartDataProviderPro.tsx @@ -8,7 +8,6 @@ import { PluginProvider, SeriesProvider, AnimationProvider, - SvgRefProvider, SizeProvider, } from '@mui/x-charts/internals'; import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context'; @@ -49,7 +48,7 @@ function ChartDataProviderPro(props: ChartDataProviderProProps) { - {children} + {children} diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx index 8a61ef8212f6..9c9d5a386118 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx @@ -2,7 +2,6 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils'; import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; import { expect } from 'chai'; -import { SvgRefProvider } from '../context/SvgRefProvider'; import { SizeProvider } from '../context/SizeProvider'; describe('', () => { @@ -18,14 +17,12 @@ describe('', () => { render( - - - - - + + + , ); diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 3e17bd99572a..831d12f47b5e 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -47,7 +47,7 @@ const ChartsSurface = React.forwardRef(functi ref: React.Ref, ) { const { width, height, left, right, top, bottom } = useDrawingArea(); - const { hasIntrinsicSize, containerRef, inHeight, inWidth } = useSize(); + const { hasIntrinsicSize, svgRef: containerRef, inHeight, inWidth } = useSize(); const handleRef = useForkRef(containerRef as any, 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 29d830331757..9d44296c4cd7 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -107,11 +107,6 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { }, [defaultXAxisId, defaultYAxisId, series, seriesOrder, xAxis, yAxis, drawingArea]); React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return undefined; - } - function getClosestPoint( event: MouseEvent, ): @@ -119,6 +114,11 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { | 'outside-chart' | 'outside-voronoi-max-radius' | 'no-point-found' { + const element = svgRef.current; + if (element === null) { + return 'no-point-found'; + } + // Get mouse coordinate in global SVG space const svgPoint = getSVGPoint(element, event); @@ -216,6 +216,11 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { onItemClick(event, { type: 'scatter', seriesId, dataIndex }); }; + const element = svgRef.current; + if (element === null) { + return undefined; + } + element.addEventListener('pointerleave', handleMouseLeave); element.addEventListener('pointermove', handleMouseMove); element.addEventListener('click', handleMouseClick); diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index 6126367e056c..a0bdf9eaac2d 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -6,7 +6,6 @@ import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; import { DrawingAreaProvider, DrawingAreaProviderProps } from '../context/DrawingAreaProvider'; import { GaugeProvider, GaugeProviderProps } from './GaugeProvider'; import { SizeProvider, useSize } from '../context/SizeProvider'; -import { SvgRefProvider } from '../context/SvgRefProvider'; export interface GaugeContainerProps extends Omit, @@ -46,7 +45,7 @@ const ResizableContainerRoot = styled('div', { })); function ResizableContainer(props: any) { - const { inHeight, inWidth, hasIntrinsicSize, containerRef } = useSize(); + const { inHeight, inWidth, hasIntrinsicSize, svgRef: containerRef } = useSize(); return ( - - - + + - - - - + {children} + + + + ); }); diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index 5f7618e39f85..f3ab4eeadde4 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -13,7 +13,6 @@ import { AnimationProvider, AnimationProviderProps } from '../AnimationProvider' import { ZAxisContextProvider, ZAxisContextProviderProps } from '../ZAxisContextProvider'; import { HighlightedProvider, HighlightedProviderProps } from '../HighlightedProvider'; import { SizeProvider, SizeProviderProps } from '../SizeProvider'; -import { SvgRefProvider } from '../SvgRefProvider'; export type ChartDataProviderProps = Omit< SizeProviderProps & @@ -63,9 +62,7 @@ function ChartDataProvider(props: ChartDataProviderProps) { - - {children} - + {children} diff --git a/packages/x-charts/src/context/SizeProvider/Size.types.ts b/packages/x-charts/src/context/SizeProvider/Size.types.ts index 811e5dcd498d..46a477ce5551 100644 --- a/packages/x-charts/src/context/SizeProvider/Size.types.ts +++ b/packages/x-charts/src/context/SizeProvider/Size.types.ts @@ -14,9 +14,9 @@ export interface SizeProviderProps { export interface SizeContextState extends Required> { /** - * The ref of the container element that the chart is rendered in. + * The ref of the svg element that the chart is rendered in. */ - containerRef: React.RefObject; + svgRef: React.RefObject; /** * If the chart has a defined size. */ diff --git a/packages/x-charts/src/context/SizeProvider/SizeContext.ts b/packages/x-charts/src/context/SizeProvider/SizeContext.ts index f9c4b22b7a9c..b60bd58d9a8b 100644 --- a/packages/x-charts/src/context/SizeProvider/SizeContext.ts +++ b/packages/x-charts/src/context/SizeProvider/SizeContext.ts @@ -7,7 +7,7 @@ export const SizeContext = React.createContext>( isInitialized: false, data: { hasIntrinsicSize: false, - containerRef: null as any, + svgRef: { current: null as any }, height: 0, width: 0, }, diff --git a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts b/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts index 032af4225d68..5ebf61cbadfc 100644 --- a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts +++ b/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts @@ -9,7 +9,7 @@ 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 rootRef = React.useRef(null); const [width, setWidth] = React.useState(0); const [height, setHeight] = React.useState(0); @@ -112,7 +112,7 @@ export const useChartContainerDimensions = (inWidth?: number, inHeight?: number) const finalHeight = inHeight ?? height; return { - containerRef: rootRef, + svgRef: rootRef, width: finalWidth, height: finalHeight, hasIntrinsicSize: finalWidth > 0 && finalHeight > 0, diff --git a/packages/x-charts/src/context/SvgRefProvider/SvgRef.types.ts b/packages/x-charts/src/context/SvgRefProvider/SvgRef.types.ts deleted file mode 100644 index 92449792410f..000000000000 --- a/packages/x-charts/src/context/SvgRefProvider/SvgRef.types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react'; - -export interface SvgRefProviderProps { - children: React.ReactNode; -} - -export type SvgRefState = { - svgRef: React.Ref; - surfaceRef: React.Ref; -}; diff --git a/packages/x-charts/src/context/SvgRefProvider/SvgRefContext.tsx b/packages/x-charts/src/context/SvgRefProvider/SvgRefContext.tsx deleted file mode 100644 index 139761daee62..000000000000 --- a/packages/x-charts/src/context/SvgRefProvider/SvgRefContext.tsx +++ /dev/null @@ -1,16 +0,0 @@ -'use client'; -import * as React from 'react'; -import { Initializable } from '../context.types'; -import { SvgRefState } from './SvgRef.types'; - -export const SvgRefContext = React.createContext>({ - isInitialized: false, - data: { - svgRef: { current: null }, - surfaceRef: { current: null }, - }, -}); - -if (process.env.NODE_ENV !== 'production') { - SvgRefContext.displayName = 'SvgRefContext'; -} diff --git a/packages/x-charts/src/context/SvgRefProvider/SvgRefProvider.tsx b/packages/x-charts/src/context/SvgRefProvider/SvgRefProvider.tsx deleted file mode 100644 index fec512d29a82..000000000000 --- a/packages/x-charts/src/context/SvgRefProvider/SvgRefProvider.tsx +++ /dev/null @@ -1,18 +0,0 @@ -'use client'; -import * as React from 'react'; -import useForkRef from '@mui/utils/useForkRef'; -import { SvgRefProviderProps } from './SvgRef.types'; -import { SvgRefContext } from './SvgRefContext'; - -export function SvgRefProvider(props: SvgRefProviderProps) { - const { children } = props; - const svgRef = React.useRef(null); - const surfaceRef = useForkRef(svgRef); - - const refValue = React.useMemo( - () => ({ isInitialized: true, data: { svgRef, surfaceRef } }), - [svgRef, surfaceRef], - ); - - return {children}; -} diff --git a/packages/x-charts/src/context/SvgRefProvider/index.ts b/packages/x-charts/src/context/SvgRefProvider/index.ts deleted file mode 100644 index f6d75d4f23d6..000000000000 --- a/packages/x-charts/src/context/SvgRefProvider/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './SvgRef.types'; -export * from './SvgRefProvider'; -export * from './SvgRefContext'; -export * from './useSurfaceRef'; diff --git a/packages/x-charts/src/context/SvgRefProvider/useSurfaceRef.ts b/packages/x-charts/src/context/SvgRefProvider/useSurfaceRef.ts deleted file mode 100644 index 5c05ae4d1200..000000000000 --- a/packages/x-charts/src/context/SvgRefProvider/useSurfaceRef.ts +++ /dev/null @@ -1,18 +0,0 @@ -'use client'; -import * as React from 'react'; -import { SvgRefContext } from './SvgRefContext'; - -export function useSurfaceRef(): React.MutableRefObject { - const { isInitialized, data } = React.useContext(SvgRefContext); - - if (!isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the svg ref context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } - - return data.surfaceRef as React.MutableRefObject; -} diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx index e6d16c2beab9..fe2baeb9d312 100644 --- a/packages/x-charts/src/hooks/useSvgRef.test.tsx +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -2,22 +2,13 @@ import * as React from 'react'; import { expect } from 'chai'; import { ErrorBoundary, createRenderer, screen } from '@mui/internal-test-utils'; import { useSvgRef } from './useSvgRef'; -import { SvgRefProvider, useSurfaceRef } from '../context/SvgRefProvider'; +import { SizeProvider } from '../context/SizeProvider'; function UseSvgRef() { const ref = useSvgRef(); return
{ref.current?.id}
; } -function UseSurfaceRef({ children }: any) { - const ref = useSurfaceRef(); - return ( - - {children} - - ); -} - describe('useSvgRef', () => { const { render } = createRenderer(); @@ -51,11 +42,9 @@ describe('useSvgRef', () => { it('should not throw an error when parent context is present', async () => { function RenderDrawingProvider() { return ( - - - - - + + + ); } diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index ef1e3fe842ac..549e984bf421 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -1,9 +1,9 @@ 'use client'; import * as React from 'react'; -import { SvgRefContext } from '../context/SvgRefProvider'; +import { SizeContext } from '../context/SizeProvider'; -export function useSvgRef(): React.MutableRefObject { - const { isInitialized, data } = React.useContext(SvgRefContext); +export function useSvgRef(): React.RefObject { + const { isInitialized, data } = React.useContext(SizeContext); if (!isInitialized) { throw new Error( @@ -14,5 +14,5 @@ export function useSvgRef(): React.MutableRefObject { ); } - return data.svgRef as React.MutableRefObject; + return data.svgRef; } diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts index 9b185361457d..ce482bd7aa30 100644 --- a/packages/x-charts/src/internals/index.ts +++ b/packages/x-charts/src/internals/index.ts @@ -34,7 +34,6 @@ export type * from '../context/context.types'; export { getAxisExtremum } from '../context/CartesianProvider/getAxisExtremum'; export * from '../context/ChartDataProvider'; export * from '../context/SizeProvider'; -export * from '../context/SvgRefProvider'; // series configuration export * from '../models/seriesType/config'; From f00e50ab46e6b8e927c56ba12cdee4154bed5df9 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Thu, 21 Nov 2024 14:53:34 +0100 Subject: [PATCH 05/24] formatting --- packages/x-charts/src/ChartsSurface/ChartsSurface.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 831d12f47b5e..0a03d8e6ed17 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -36,7 +36,6 @@ const ChartsSurfaceStyles = styled('svg', { alignItems: 'center', justifyContent: 'center', overflow: 'hidden', - // This prevents default touch actions when using the svg on mobile devices. // For example, prevent page scroll & zoom. touchAction: 'none', From 42591eb2580ba1da282c9e0ec04834730ce4e992 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Thu, 21 Nov 2024 15:08:00 +0100 Subject: [PATCH 06/24] fix test --- packages/x-charts/src/hooks/useSvgRef.test.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx index fe2baeb9d312..06534b013723 100644 --- a/packages/x-charts/src/hooks/useSvgRef.test.tsx +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -6,7 +6,11 @@ import { SizeProvider } from '../context/SizeProvider'; function UseSvgRef() { const ref = useSvgRef(); - return
{ref.current?.id}
; + return ( + + {ref.current?.id} + + ); } describe('useSvgRef', () => { From 5c89ab6615eccebefff5a5fcdcd4e0b6db8652b2 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Thu, 21 Nov 2024 15:22:34 +0100 Subject: [PATCH 07/24] force mutable ref --- packages/x-charts/src/hooks/useSvgRef.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index 549e984bf421..129f9d2b199a 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { SizeContext } from '../context/SizeProvider'; -export function useSvgRef(): React.RefObject { +export function useSvgRef(): React.MutableRefObject { const { isInitialized, data } = React.useContext(SizeContext); if (!isInitialized) { @@ -14,5 +14,5 @@ export function useSvgRef(): React.RefObject { ); } - return data.svgRef; + return data.svgRef as React.MutableRefObject; } From f6c3fc8e15b56cd80a9117c0b3b06e42f079654f Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Thu, 21 Nov 2024 15:56:34 +0100 Subject: [PATCH 08/24] fix test --- packages/x-charts/src/hooks/useSvgRef.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx index 06534b013723..7edac99637a3 100644 --- a/packages/x-charts/src/hooks/useSvgRef.test.tsx +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -46,7 +46,7 @@ describe('useSvgRef', () => { it('should not throw an error when parent context is present', async () => { function RenderDrawingProvider() { return ( - + ); From ba2f70ecabe94b41f275cfc77c992cb24bdbc283 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 22 Nov 2024 17:04:48 +0100 Subject: [PATCH 09/24] Improve component documentation --- docs/data/charts/composition/composition.md | 53 +++++++++++++- docs/data/chartsApiPages.ts | 4 ++ .../pages/x/api/charts/chart-data-provider.js | 23 ++++++ .../x/api/charts/chart-data-provider.json | 70 +++++++++++++++++++ docs/pages/x/api/charts/charts-surface.json | 2 +- .../chart-container/chart-container.json | 2 +- .../chart-data-provider.json | 42 +++++++++++ .../charts/charts-surface/charts-surface.json | 2 +- .../src/ChartContainer/ChartContainer.tsx | 24 +++++++ .../src/ChartsSurface/ChartsSurface.tsx | 14 ++++ .../ChartDataProvider/ChartDataProvider.tsx | 27 +++++++ scripts/buildApiDocs/chartsSettings/index.ts | 3 + 12 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 docs/pages/x/api/charts/chart-data-provider.js create mode 100644 docs/pages/x/api/charts/chart-data-provider.json create mode 100644 docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index 657c8724c135..d51710e6b46f 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -2,7 +2,7 @@ title: React Chart composition productId: x-charts githubLabel: 'component: charts' -components: ChartContainer, ChartContainerPro, ChartsGrid +components: ChartContainer, ChartContainerPro, ChartsGrid, ChartDataProvider, ChartsSurface packageName: '@mui/x-charts' --- @@ -13,8 +13,55 @@ packageName: '@mui/x-charts' ## Overview The `@mui/x-charts` follows an architecture based on context providers. -The overall idea is to pass your series and axes definitions to a single component: the ``. -This component transforms the data and makes it available to its children. +The overall idea is to pass your series and axes definitions to special components. +This component transforms the data and makes it available to its children, which can be composed. + +There are two main classes of components, which are used to create a chart. + +### 1. Structural components + +These are used to define the chart's structure and data. + +#### The `ChartDataProvider` and `ChartsSurface` components + +As the name suggests, the `ChartDataProvider` provides the data to the children components. +While the `ChartsSurface` renders the SVG elements. + +```jsx + + {children} + +``` + +#### The `ChartContainer` helper + +This component is a composition of the two previous components. +It can be used instead of them when you don't need to customize anything outside the chart's graphical elements. + +```jsx +{children} +``` + +### 2. Graphical components + +These are any component that render the graphical elements of the chart. They are the children of the **Structural components** shown above. +There are many of them, so we will not list them all here. You can even [create your own components](/x/react-charts/components/). + +Some examples of graphical components are: + +- `LinePlot` +- `BarPlot` +- `ChartsXAxis` +- `ChartsLegend` +- `ChartsTooltip` + +The `ChartDataProvider` component allows you to access the internal data and render your own components, especially `HTML` components. + +The main idea is very simple, the `ChartDataProvider` component provides a context with all the data needed to render a chart. +While the `ChartsSurface` component is responsible for rendering the SVG elements. + +This allows you to create your own components and use the data provided by the `ChartDataProvider` to render them. +Allowing for a much simpler way to create custom components, like legends, by using `HTML` elements. Based on the data provided by the container, you can render some graphical elements with provided subcomponents, such as `` or ``. Or you can [create your own components](/x/react-charts/components/). diff --git a/docs/data/chartsApiPages.ts b/docs/data/chartsApiPages.ts index 724d92693ea9..86a827ece84d 100644 --- a/docs/data/chartsApiPages.ts +++ b/docs/data/chartsApiPages.ts @@ -47,6 +47,10 @@ const chartsApiPages: MuiPage[] = [ title: 'ChartContainerPro', plan: 'pro', }, + { + pathname: '/x/api/charts/chart-data-provider', + title: 'ChartDataProvider', + }, { pathname: '/x/api/charts/charts-axis', title: 'ChartsAxis', diff --git a/docs/pages/x/api/charts/chart-data-provider.js b/docs/pages/x/api/charts/chart-data-provider.js new file mode 100644 index 000000000000..73a45a0bc932 --- /dev/null +++ b/docs/pages/x/api/charts/chart-data-provider.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './chart-data-provider.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/charts/chart-data-provider', + false, + /\.\/chart-data-provider.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/charts/chart-data-provider.json b/docs/pages/x/api/charts/chart-data-provider.json new file mode 100644 index 000000000000..001c5b9e16d9 --- /dev/null +++ b/docs/pages/x/api/charts/chart-data-provider.json @@ -0,0 +1,70 @@ +{ + "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 }>" + } + } + }, + "name": "ChartDataProvider", + "imports": [ + "import { ChartDataProvider } from '@mui/x-charts/context';", + "import { ChartDataProvider } from '@mui/x-charts';", + "import { ChartDataProvider } from '@mui/x-charts-pro';" + ], + "classes": [], + "spread": false, + "themeDefaultProps": false, + "muiName": "MuiChartDataProvider", + "forwardsRefTo": "SVGSVGElement", + "filename": "/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/charts-surface.json b/docs/pages/x/api/charts/charts-surface.json index ae4ebc5a067c..e5abdd4769ee 100644 --- a/docs/pages/x/api/charts/charts-surface.json +++ b/docs/pages/x/api/charts/charts-surface.json @@ -12,6 +12,6 @@ "muiName": "MuiChartsSurface", "filename": "/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx", "inheritance": null, - "demos": "", + "demos": "", "cssComponent": false } 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 a15bc34c6f24..45f4bcacdeca 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,5 @@ { - "componentDescription": "", + "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": { 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 new file mode 100644 index 000000000000..57a8f05201d9 --- /dev/null +++ b/docs/translations/api-docs/charts/chart-data-provider/chart-data-provider.json @@ -0,0 +1,42 @@ +{ + "componentDescription": "Orchestrates the data providers for the chart components and hooks.\n\nUse this component if you have custom HTML components that need to access the chart data.", + "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." + }, + "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." + }, + "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." + }, + "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/docs/translations/api-docs/charts/charts-surface/charts-surface.json b/docs/translations/api-docs/charts/charts-surface/charts-surface.json index 40b01b75badb..337a2c55eefd 100644 --- a/docs/translations/api-docs/charts/charts-surface/charts-surface.json +++ b/docs/translations/api-docs/charts/charts-surface/charts-surface.json @@ -1,5 +1,5 @@ { - "componentDescription": "", + "componentDescription": "It provides the drawing area for the chart elements.\nIt is the root `` of all the chart elements.\n\nIt also provides the `title` and `desc` elements for the chart.", "propDescriptions": { "disableAxisListener": { "description": "If true, the charts will not listen to the mouse move event. It might break interactive features, but will improve performance." diff --git a/packages/x-charts/src/ChartContainer/ChartContainer.tsx b/packages/x-charts/src/ChartContainer/ChartContainer.tsx index df2caef81db2..a938fb051e30 100644 --- a/packages/x-charts/src/ChartContainer/ChartContainer.tsx +++ b/packages/x-charts/src/ChartContainer/ChartContainer.tsx @@ -7,6 +7,30 @@ import { ChartsSurface, ChartsSurfaceProps } from '../ChartsSurface'; export interface ChartContainerProps extends ChartDataProviderProps, ChartsSurfaceProps {} +/** + * 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 ChartContainer = React.forwardRef(function ChartContainer( props: ChartContainerProps, ref: React.Ref, diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index 0a03d8e6ed17..a7975f859d32 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -41,6 +41,20 @@ const ChartsSurfaceStyles = styled('svg', { touchAction: 'none', })); +/** + * It provides the drawing area for the chart elements. + * It is the root `` of all the chart elements. + * + * It also provides the `title` and `desc` elements for the chart. + * + * Demos: + * + * - [Composition](http://localhost:3001/x/react-charts/composition/) + * + * API: + * + * - [ChartsSurface API](https://mui.com/x/api/charts/charts-surface/) + */ const ChartsSurface = React.forwardRef(function ChartsSurface( inProps: ChartsSurfaceProps, ref: React.Ref, diff --git a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx index f3ab4eeadde4..f8fbada68ecc 100644 --- a/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx +++ b/packages/x-charts/src/context/ChartDataProvider/ChartDataProvider.tsx @@ -40,6 +40,33 @@ export type ChartDataProviderProps = Omit< children?: React.ReactNode; }; +/** + * Orchestrates the data providers for the chart components and hooks. + * + * Use this component if you have custom HTML components that need to access the chart data. + * + * Demos: + * + * - [Composition](http://localhost:3001/x/react-charts/composition/) + * + * API: + * + * - [ChartDataProvider API](https://mui.com/x/api/charts/chart-data-provider/) + * + * @example + * ```jsx + * + * + * + * + * + * {'Custom Legend Component'} + * + * ``` + */ function ChartDataProvider(props: ChartDataProviderProps) { const { children, diff --git a/scripts/buildApiDocs/chartsSettings/index.ts b/scripts/buildApiDocs/chartsSettings/index.ts index a9631f07f4ea..2c9dabdcb7e7 100644 --- a/scripts/buildApiDocs/chartsSettings/index.ts +++ b/scripts/buildApiDocs/chartsSettings/index.ts @@ -54,6 +54,9 @@ export default chartsApiPages; translationLanguages: LANGUAGES, skipComponent(filename) { if (filename.includes('/context/')) { + if (filename.endsWith('ChartDataProvider.tsx')) { + return false; + } return true; } return [ From 0eb34941fa3f120c2be53b3e3c390e510a24f356 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 22 Nov 2024 17:40:52 +0100 Subject: [PATCH 10/24] add docs and demo --- docs/data/charts/components/HtmlLegend.js | 66 +++++++++++++++++++ docs/data/charts/components/HtmlLegend.tsx | 66 +++++++++++++++++++ .../charts/components/HtmlLegend.tsx.preview | 14 ++++ docs/data/charts/components/components.md | 17 +++++ docs/data/charts/composition/composition.md | 18 ++--- 5 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 docs/data/charts/components/HtmlLegend.js create mode 100644 docs/data/charts/components/HtmlLegend.tsx create mode 100644 docs/data/charts/components/HtmlLegend.tsx.preview diff --git a/docs/data/charts/components/HtmlLegend.js b/docs/data/charts/components/HtmlLegend.js new file mode 100644 index 000000000000..fbdc1236b55d --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.js @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { unstable_useBarSeries } from '@mui/x-charts/hooks'; +import { ChartDataProvider } from '@mui/x-charts/context'; +import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; +import { BarPlot } from '@mui/x-charts/BarChart'; +import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; +import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; + +function MyCustomLegend() { + const s = unstable_useBarSeries(); + return ( + + + {Object.values(s?.series ?? []).map((v) => { + return ( + + + + + ); + })} + +
+
+
{`${v.label}`}
+ ); +} + +const veryLongText = + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully."; + +export default function HtmlLegend() { + return ( + + + + + + + + + + + ); +} diff --git a/docs/data/charts/components/HtmlLegend.tsx b/docs/data/charts/components/HtmlLegend.tsx new file mode 100644 index 000000000000..fbdc1236b55d --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.tsx @@ -0,0 +1,66 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import { unstable_useBarSeries } from '@mui/x-charts/hooks'; +import { ChartDataProvider } from '@mui/x-charts/context'; +import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; +import { BarPlot } from '@mui/x-charts/BarChart'; +import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; +import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; + +function MyCustomLegend() { + const s = unstable_useBarSeries(); + return ( + + + {Object.values(s?.series ?? []).map((v) => { + return ( + + + + + ); + })} + +
+
+
{`${v.label}`}
+ ); +} + +const veryLongText = + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully."; + +export default function HtmlLegend() { + return ( + + + + + + + + + + + ); +} diff --git a/docs/data/charts/components/HtmlLegend.tsx.preview b/docs/data/charts/components/HtmlLegend.tsx.preview new file mode 100644 index 000000000000..3f05cd43a0a0 --- /dev/null +++ b/docs/data/charts/components/HtmlLegend.tsx.preview @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index be2f67d72870..49386f1f57ce 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -76,3 +76,20 @@ By using `invert`, the value associated with the current mouse coordinate `y` ca ``` {{"demo": "ScaleDemo.js"}} + +## HTML components + +With the introduction of the `ChartDataProvider` in v8, the chart data can be accessed from any component. +This allows you to create HTML components that interact with the charts data. + +In the next example, notice that `MyCustomLegend` component displays the series names and colors. You can expand the code to see how it works. +This creates an html `table` element, which handles long series names better than the default legend. + +{{"demo": "HtmlLegend.js"}} + +:::warning +Note that the HTML components are not part of the SVG hierarchy. Hence, they should be placed outside the `` component, +but inside the `` component. Else they will not be visible. + +If you want to position an HTML component relative to the SVG, you can use the `useDrawingArea()` hook to get the SVG's position and size. +::: diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index d51710e6b46f..0449ea39860c 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -22,6 +22,11 @@ There are two main classes of components, which are used to create a chart. These are used to define the chart's structure and data. +:::info +Most of the demos here will be using the `ChartContainer` component. +To see demos using the separate `ChartDataProvider` and `ChartsSurface` components, check the [HTML components documentation](/x/react-charts/components/#html-components). +::: + #### The `ChartDataProvider` and `ChartsSurface` components As the name suggests, the `ChartDataProvider` provides the data to the children components. @@ -36,7 +41,7 @@ While the `ChartsSurface` renders the SVG elements. #### The `ChartContainer` helper This component is a composition of the two previous components. -It can be used instead of them when you don't need to customize anything outside the chart's graphical elements. +It can be used instead of them when there is no need to customize anything outside the chart's graphical elements. ```jsx {children} @@ -55,17 +60,6 @@ Some examples of graphical components are: - `ChartsLegend` - `ChartsTooltip` -The `ChartDataProvider` component allows you to access the internal data and render your own components, especially `HTML` components. - -The main idea is very simple, the `ChartDataProvider` component provides a context with all the data needed to render a chart. -While the `ChartsSurface` component is responsible for rendering the SVG elements. - -This allows you to create your own components and use the data provided by the `ChartDataProvider` to render them. -Allowing for a much simpler way to create custom components, like legends, by using `HTML` elements. - -Based on the data provided by the container, you can render some graphical elements with provided subcomponents, such as `` or ``. -Or you can [create your own components](/x/react-charts/components/). - ## Container options ### Responsive From 23aee9343991953bc8b6b56663afc226cf383a57 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 22 Nov 2024 18:06:44 +0100 Subject: [PATCH 11/24] add more text for visual testing --- docs/data/charts/components/HtmlLegend.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/charts/components/HtmlLegend.tsx b/docs/data/charts/components/HtmlLegend.tsx index fbdc1236b55d..a58701b379a8 100644 --- a/docs/data/charts/components/HtmlLegend.tsx +++ b/docs/data/charts/components/HtmlLegend.tsx @@ -42,7 +42,7 @@ function MyCustomLegend() { } const veryLongText = - "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully."; + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully. This is a very long sentence that should be fully readable."; export default function HtmlLegend() { return ( From 7e03c810f353910b702b5653b9d11a919966251f Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 22 Nov 2024 18:31:55 +0100 Subject: [PATCH 12/24] fix scripts --- docs/data/charts/components/HtmlLegend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/charts/components/HtmlLegend.js b/docs/data/charts/components/HtmlLegend.js index fbdc1236b55d..a58701b379a8 100644 --- a/docs/data/charts/components/HtmlLegend.js +++ b/docs/data/charts/components/HtmlLegend.js @@ -42,7 +42,7 @@ function MyCustomLegend() { } const veryLongText = - "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully."; + "Second Series. You should always try to avoid long sentences. But oftentimes, it's not possible. So, we need to handle them gracefully. This is a very long sentence that should be fully readable."; export default function HtmlLegend() { return ( From a210c2567ef4e040bc636aaa05848ac5aa4088c2 Mon Sep 17 00:00:00 2001 From: Jose C Quintas Jr Date: Mon, 25 Nov 2024 16:02:47 +0100 Subject: [PATCH 13/24] Apply suggestions from code review Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com> Signed-off-by: Jose C Quintas Jr --- docs/data/charts/composition/composition.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index 0449ea39860c..d95710938f2d 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -18,7 +18,7 @@ This component transforms the data and makes it available to its children, which There are two main classes of components, which are used to create a chart. -### 1. Structural components +### Structural components These are used to define the chart's structure and data. @@ -27,7 +27,7 @@ Most of the demos here will be using the `ChartContainer` component. To see demos using the separate `ChartDataProvider` and `ChartsSurface` components, check the [HTML components documentation](/x/react-charts/components/#html-components). ::: -#### The `ChartDataProvider` and `ChartsSurface` components +#### The Data Provider and Surface components As the name suggests, the `ChartDataProvider` provides the data to the children components. While the `ChartsSurface` renders the SVG elements. @@ -47,9 +47,10 @@ It can be used instead of them when there is no need to customize anything outsi {children} ``` -### 2. Graphical components +### Graphical components -These are any component that render the graphical elements of the chart. They are the children of the **Structural components** shown above. +These are any component that render the graphical elements of the chart. +They are the children of the **Structural components** shown above. There are many of them, so we will not list them all here. You can even [create your own components](/x/react-charts/components/). Some examples of graphical components are: From a04bf059eca53d8a578bc09e1a209151608e9ef3 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 26 Nov 2024 17:04:26 +0100 Subject: [PATCH 14/24] fix tooltips --- .../src/ChartsSurface/ChartsSurface.test.tsx | 19 +++++++++++-------- .../src/ChartsSurface/ChartsSurface.tsx | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx index 9c9d5a386118..6e917eedb054 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.test.tsx @@ -3,6 +3,7 @@ import { createRenderer } from '@mui/internal-test-utils'; import { ChartsSurface } from '@mui/x-charts/ChartsSurface'; import { expect } from 'chai'; import { SizeProvider } from '../context/SizeProvider'; +import { ChartProvider } from '../context/ChartProvider'; describe('', () => { // JSDOM doesn't implement SVGElement @@ -16,14 +17,16 @@ describe('', () => { const ref = React.createRef(); render( - - - - - , + + + + + + + , ); expect(ref.current instanceof SVGElement, 'ref is a SVGElement').to.equal(true); diff --git a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx index a7975f859d32..2403575a9b64 100644 --- a/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx +++ b/packages/x-charts/src/ChartsSurface/ChartsSurface.tsx @@ -5,7 +5,7 @@ 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'; +import { useDrawingArea, useSvgRef } from '../hooks'; import { useSize } from '../context/SizeProvider'; import type { SizeContextState } from '../context/SizeProvider'; @@ -61,7 +61,8 @@ const ChartsSurface = React.forwardRef(functi ) { const { width, height, left, right, top, bottom } = useDrawingArea(); const { hasIntrinsicSize, svgRef: containerRef, inHeight, inWidth } = useSize(); - const handleRef = useForkRef(containerRef as any, ref); + const svgRef = useSvgRef(); + const handleRef = useForkRef(containerRef, svgRef, ref); const themeProps = useThemeProps({ props: inProps, name: 'MuiChartsSurface' }); const { children, disableAxisListener = false, className, title, desc, ...other } = themeProps; From aa43b39b570879ef9f68069b5250787af892930c Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 26 Nov 2024 17:21:42 +0100 Subject: [PATCH 15/24] return outside-chart --- .../x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index 1264ab9ea036..2db6330b0087 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -116,7 +116,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { | 'no-point-found' { const element = svgRef.current; if (element === null) { - return 'no-point-found'; + return 'outside-chart'; } // Get mouse coordinate in global SVG space From d730a1d83d00e288377334e5c17ffe5b9987d4a1 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 26 Nov 2024 17:31:55 +0100 Subject: [PATCH 16/24] docs suggestions --- docs/data/charts/composition/composition.md | 37 ++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index d95710938f2d..98227965d533 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -22,29 +22,50 @@ There are two main classes of components, which are used to create a chart. These are used to define the chart's structure and data. -:::info -Most of the demos here will be using the `ChartContainer` component. -To see demos using the separate `ChartDataProvider` and `ChartsSurface` components, check the [HTML components documentation](/x/react-charts/components/#html-components). -::: - #### The Data Provider and Surface components As the name suggests, the `ChartDataProvider` provides the data to the children components. While the `ChartsSurface` renders the SVG elements. ```jsx - - {children} + + + {children} + ``` +:::info +The demos here are using the `ChartContainer` component. +To see demos using the separate `ChartDataProvider` and `ChartsSurface` components, check the [HTML components documentation](/x/react-charts/components/#html-components). +::: + #### The `ChartContainer` helper This component is a composition of the two previous components. It can be used instead of them when there is no need to customize anything outside the chart's graphical elements. ```jsx -{children} + + {children} + ``` ### Graphical components From e8abd006a18f55a1ee5faddd497ce14690282789 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 26 Nov 2024 17:41:19 +0100 Subject: [PATCH 17/24] remove useless wrapper --- .../x-charts/src/Gauge/GaugeContainer.tsx | 55 ++++--------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/packages/x-charts/src/Gauge/GaugeContainer.tsx b/packages/x-charts/src/Gauge/GaugeContainer.tsx index 425968d98bc9..43dada12fdec 100644 --- a/packages/x-charts/src/Gauge/GaugeContainer.tsx +++ b/packages/x-charts/src/Gauge/GaugeContainer.tsx @@ -5,13 +5,14 @@ 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 { SizeProvider } from '../context/SizeProvider'; import { ChartProvider } from '../context/ChartProvider'; export interface GaugeContainerProps extends Omit, Pick, - Omit { + Omit, + React.SVGProps { /** * The width of the chart in px. If not defined, it takes the width of the parent element. */ @@ -23,42 +24,12 @@ export interface GaugeContainerProps children?: React.ReactNode; } -const ResizableContainerRoot = styled('div', { - name: 'MuiGauge', - slot: 'Container', -})<{ ownerState: Pick }>(({ ownerState, theme }) => ({ - width: ownerState.width ?? '100%', - height: ownerState.height ?? '100%', - display: 'flex', - position: 'relative', - flexGrow: 1, - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - overflow: 'hidden', - '&>svg': { - width: '100%', - height: '100%', - }, +const GStyled = styled('g')(({ theme }) => ({ '& text': { fill: (theme.vars || theme).palette.text.primary, }, })); -function ResizableContainer(props: any) { - const { inHeight, inWidth, hasIntrinsicSize, svgRef: containerRef } = useSize(); - - return ( - - {hasIntrinsicSize && props.children} - - ); -} - const GaugeContainer = React.forwardRef(function GaugeContainer( props: GaugeContainerProps, ref: React.Ref, @@ -99,23 +70,19 @@ const GaugeContainer = React.forwardRef(function GaugeContainer( cx={cx} cy={cy} > - - - + +
From 5fe575270051ca80023d7612ace2c0b09e32ed0d Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 26 Nov 2024 19:35:31 +0100 Subject: [PATCH 18/24] Add error in dev mode --- .../SizeProvider/useChartContainerDimensions.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts b/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts index 5ebf61cbadfc..4e4d566ccb4d 100644 --- a/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts +++ b/packages/x-charts/src/context/SizeProvider/useChartContainerDimensions.ts @@ -19,6 +19,17 @@ export const useChartContainerDimensions = (inWidth?: number, inHeight?: number) const mainEl = rootRef?.current; if (!mainEl) { + if (process.env.NODE_ENV !== 'production') { + // This is mostly for internal use. + throw new Error( + [ + `MUI X: ChartContainer does not have a valid reference to the element.`, + 'This may be caused by a ref forwarding issue.', + 'Make sure that the ref from SizedProvider is forwarded correctly.', + ].join('\n'), + ); + } + return {}; } From 6d8c786312fb3a6ccf981f64844f3fe9f9a099f7 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 27 Nov 2024 12:51:07 +0100 Subject: [PATCH 19/24] revert voronoi handler changes --- .../ChartsVoronoiHandler.tsx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index 2db6330b0087..f996dcfbe56e 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -107,6 +107,11 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { }, [defaultXAxisId, defaultYAxisId, series, seriesOrder, xAxis, yAxis, drawingArea]); React.useEffect(() => { + const element = svgRef.current; + if (element === null) { + return () => {}; + } + function getClosestPoint( event: MouseEvent, ): @@ -114,13 +119,8 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { | 'outside-chart' | 'outside-voronoi-max-radius' | 'no-point-found' { - const element = svgRef.current; - if (element === null) { - return 'outside-chart'; - } - // Get mouse coordinate in global SVG space - const svgPoint = getSVGPoint(element, event); + const svgPoint = getSVGPoint(element!, event); if (!drawingArea.isPointInside(svgPoint)) { lastFind.current = undefined; @@ -216,11 +216,6 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { onItemClick(event, { type: 'scatter', seriesId, dataIndex }); }; - const element = svgRef.current; - if (element === null) { - return undefined; - } - element.addEventListener('pointerleave', handleMouseLeave); element.addEventListener('pointermove', handleMouseMove); element.addEventListener('click', handleMouseClick); From 77f988ef881e504e7288cd40208c3f8ea7e2e6d2 Mon Sep 17 00:00:00 2001 From: Jose C Quintas Jr Date: Wed, 27 Nov 2024 12:57:28 +0100 Subject: [PATCH 20/24] Apply suggestions from code review Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com> Signed-off-by: Jose C Quintas Jr --- docs/data/charts/components/components.md | 9 +++++---- docs/data/charts/composition/composition.md | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index 49386f1f57ce..d27e9da3997e 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -82,14 +82,15 @@ By using `invert`, the value associated with the current mouse coordinate `y` ca With the introduction of the `ChartDataProvider` in v8, the chart data can be accessed from any component. This allows you to create HTML components that interact with the charts data. -In the next example, notice that `MyCustomLegend` component displays the series names and colors. You can expand the code to see how it works. +In the next example, notice that `MyCustomLegend` component displays the series names and colors. This creates an html `table` element, which handles long series names better than the default legend. {{"demo": "HtmlLegend.js"}} :::warning -Note that the HTML components are not part of the SVG hierarchy. Hence, they should be placed outside the `` component, -but inside the `` component. Else they will not be visible. +Note that the HTML components are not part of the SVG hierarchy. +Hence, they should be: -If you want to position an HTML component relative to the SVG, you can use the `useDrawingArea()` hook to get the SVG's position and size. +- Outside the `` component to avoid mixing HTAM and SVG. +- Inside the `` component to get access to the data. ::: diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index 98227965d533..b50eccc99c45 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -72,7 +72,8 @@ It can be used instead of them when there is no need to customize anything outsi These are any component that render the graphical elements of the chart. They are the children of the **Structural components** shown above. -There are many of them, so we will not list them all here. You can even [create your own components](/x/react-charts/components/). +There are many of them, so we will not list them all here. +You can even [create your own components](/x/react-charts/components/). Some examples of graphical components are: From 42fc45e4e4c7d044945d5e70acf9749164cc78bd Mon Sep 17 00:00:00 2001 From: Jose C Quintas Jr Date: Wed, 27 Nov 2024 13:00:00 +0100 Subject: [PATCH 21/24] Apply suggestions from code review Signed-off-by: Jose C Quintas Jr --- docs/data/charts/composition/composition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/charts/composition/composition.md b/docs/data/charts/composition/composition.md index b50eccc99c45..4bf8606dd5db 100644 --- a/docs/data/charts/composition/composition.md +++ b/docs/data/charts/composition/composition.md @@ -72,7 +72,7 @@ It can be used instead of them when there is no need to customize anything outsi These are any component that render the graphical elements of the chart. They are the children of the **Structural components** shown above. -There are many of them, so we will not list them all here. +There are many of them, so they won't all be listed here. You can even [create your own components](/x/react-charts/components/). Some examples of graphical components are: From 4f32d59ea77d4dc2cb51501b493e655337e3a8ee Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 27 Nov 2024 13:11:07 +0100 Subject: [PATCH 22/24] fix linting --- docs/data/charts/components/components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index d27e9da3997e..10507bcbebbe 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -93,4 +93,4 @@ Hence, they should be: - Outside the `` component to avoid mixing HTAM and SVG. - Inside the `` component to get access to the data. -::: + ::: From dc57646bb4c3aec0afab53e3d20e4783a93f3e10 Mon Sep 17 00:00:00 2001 From: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:46:20 +0100 Subject: [PATCH 23/24] Update docs/data/charts/components/components.md Signed-off-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com> --- docs/data/charts/components/components.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/data/charts/components/components.md b/docs/data/charts/components/components.md index 10507bcbebbe..791c338ced4f 100644 --- a/docs/data/charts/components/components.md +++ b/docs/data/charts/components/components.md @@ -93,4 +93,5 @@ Hence, they should be: - Outside the `` component to avoid mixing HTAM and SVG. - Inside the `` component to get access to the data. - ::: + +::: From e55b66e456c4bcea872580f2739179626d4b8922 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 27 Nov 2024 14:00:44 +0100 Subject: [PATCH 24/24] suggestion --- .../src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index f996dcfbe56e..638b9c2577f5 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -107,10 +107,10 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { }, [defaultXAxisId, defaultYAxisId, series, seriesOrder, xAxis, yAxis, drawingArea]); React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return () => {}; + if (svgRef.current === null) { + return undefined; } + const element = svgRef.current; function getClosestPoint( event: MouseEvent, @@ -120,7 +120,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { | 'outside-voronoi-max-radius' | 'no-point-found' { // Get mouse coordinate in global SVG space - const svgPoint = getSVGPoint(element!, event); + const svgPoint = getSVGPoint(element, event); if (!drawingArea.isPointInside(svgPoint)) { lastFind.current = undefined;