From eb70e5a9b9bdd1cabd1a8225706e6b2c24cec0fe Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Fri, 3 May 2024 18:21:00 +0200 Subject: [PATCH] Add element to prevent unnecessary computation --- packages/x-charts/src/BarChart/BarChart.tsx | 2 + .../src/BarChart/BarElementLabelPlot.tsx | 74 +++++++++++++++++++ packages/x-charts/src/BarChart/BarPlot.tsx | 53 ++++++------- 3 files changed, 98 insertions(+), 31 deletions(-) create mode 100644 packages/x-charts/src/BarChart/BarElementLabelPlot.tsx diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index 78d7ed64dcac8..24418c8dfb5e7 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -137,6 +137,7 @@ const BarChart = React.forwardRef(function BarChart(props: BarChartProps, ref) { slots, slotProps, loading, + showLabels, } = props; const id = useId(); @@ -195,6 +196,7 @@ const BarChart = React.forwardRef(function BarChart(props: BarChartProps, ref) { slotProps={slotProps} skipAnimation={skipAnimation} onItemClick={onItemClick} + showLabels={showLabels} /> diff --git a/packages/x-charts/src/BarChart/BarElementLabelPlot.tsx b/packages/x-charts/src/BarChart/BarElementLabelPlot.tsx new file mode 100644 index 0000000000000..f873efa4373df --- /dev/null +++ b/packages/x-charts/src/BarChart/BarElementLabelPlot.tsx @@ -0,0 +1,74 @@ +import * as React from 'react'; + +import { to, useTransition } from '@react-spring/web'; +import type { CompletedBarData } from './BarPlot'; +import { BarElementLabel } from './BarElementLabel'; + +const getOutStyle = ({ layout, yOrigin, x, width, y, xOrigin, height }: CompletedBarData) => ({ + ...(layout === 'vertical' + ? { + y: yOrigin, + x, + height: 0, + width, + } + : { + y, + x: xOrigin, + height, + width: 0, + }), +}); + +const getInStyle = ({ x, width, y, height }: CompletedBarData) => ({ + y, + x, + height, + width, +}); + +type BarElementLabelPlotProps = { + bars: CompletedBarData[]; + skipAnimation?: boolean; +}; + +/** + * @ignore - internal component. + */ +function BarElementLabelPlot(props: BarElementLabelPlotProps) { + const { bars, skipAnimation, ...other } = props; + + const barLabelTransition = useTransition(bars, { + keys: (bar) => `${bar.seriesId}-${bar.dataIndex}`, + from: getOutStyle, + leave: null, + enter: getInStyle, + update: getInStyle, + immediate: skipAnimation, + }); + + return ( + + {barLabelTransition((style, { seriesId, dataIndex, color, value, width, height }) => ( + (x ?? 0) + w / 2), + y: to([(style as any).y, (style as any).height], (y, w) => (y ?? 0) + w / 2), + } as any + } + labelText={value ? value.toString() : null} + /> + ))} + + ); +} + +export { BarElementLabelPlot }; diff --git a/packages/x-charts/src/BarChart/BarPlot.tsx b/packages/x-charts/src/BarChart/BarPlot.tsx index 3155b2c368e2c..7d70243477840 100644 --- a/packages/x-charts/src/BarChart/BarPlot.tsx +++ b/packages/x-charts/src/BarChart/BarPlot.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { to, useTransition } from '@react-spring/web'; +import { useTransition } from '@react-spring/web'; import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { BarElement, BarElementSlotProps, BarElementSlots } from './BarElement'; @@ -11,7 +11,8 @@ import { BarItemIdentifier, BarSeriesType } from '../models'; import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../constants'; import { SeriesId } from '../models/seriesType/common'; import getColor from './getColor'; -import { BarElementLabel, BarElementLabelSlotProps, BarElementLabelSlots } from './BarElementLabel'; +import { BarElementLabelSlotProps, BarElementLabelSlots } from './BarElementLabel'; +import { BarElementLabelPlot } from './BarElementLabelPlot'; /** * Solution of the equations @@ -49,7 +50,7 @@ export interface BarPlotSlots extends BarElementSlots, BarElementLabelSlots {} export interface BarPlotSlotProps extends BarElementSlotProps, BarElementLabelSlotProps {} -export interface BarPlotProps extends BarPlotSlotProps { +export interface BarPlotProps { /** * If `true`, animations are skipped. * @default false @@ -64,6 +65,20 @@ export interface BarPlotProps extends BarPlotSlotProps { event: React.MouseEvent, barItemIdentifier: BarItemIdentifier, ) => void; + /** + * If `true`, displays the value labels on the bars. + */ + showLabels?: boolean; + /** + * The props used for each component slot. + * @default {} + */ + slotProps?: BarPlotSlotProps; + /** + * Overridable component slots. + * @default {} + */ + slots?: BarPlotSlots; } export interface CompletedBarData { @@ -246,7 +261,7 @@ const getInStyle = ({ x, width, y, height }: CompletedBarData) => ({ */ function BarPlot(props: BarPlotProps) { const completedData = useAggregatedData(); - const { skipAnimation, onItemClick, ...other } = props; + const { skipAnimation, onItemClick, showLabels, ...other } = props; const transition = useTransition(completedData, { keys: (bar) => `${bar.seriesId}-${bar.dataIndex}`, @@ -257,15 +272,6 @@ function BarPlot(props: BarPlotProps) { immediate: skipAnimation, }); - const barLabelTransition = useTransition(completedData, { - keys: (bar) => `${bar.seriesId}-${bar.dataIndex}`, - from: getOutStyle, - leave: null, - enter: getInStyle, - update: getInStyle, - immediate: skipAnimation, - }); - return ( {transition((style, { seriesId, dataIndex, color, highlightScope }) => ( @@ -284,24 +290,9 @@ function BarPlot(props: BarPlotProps) { style={style} /> ))} - {barLabelTransition((style, { seriesId, dataIndex, color, value, width, height }) => ( - (x ?? 0) + w / 2), - y: to([(style as any).y, (style as any).height], (y, w) => (y ?? 0) + w / 2), - } as any - } - labelText={value ? value.toString() : null} - /> - ))} + {showLabels && ( + + )} ); }