Skip to content

Commit

Permalink
[charts] Add Initializable type and behaviour to allow checking if a …
Browse files Browse the repository at this point in the history
…complex context has been initialized. (#13365)
  • Loading branch information
JCQuintas authored Jun 5, 2024
1 parent 6716fd4 commit 8f0778b
Show file tree
Hide file tree
Showing 27 changed files with 266 additions and 84 deletions.
4 changes: 2 additions & 2 deletions packages/x-charts/src/BarChart/BarPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { useTransition } from '@react-spring/web';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { BarElement, BarElementSlotProps, BarElementSlots } from './BarElement';
import { AxisDefaultized } from '../models/axis';
Expand All @@ -14,6 +13,7 @@ import { BarClipPath } from './BarClipPath';
import { BarLabelItemProps, BarLabelSlotProps, BarLabelSlots } from './BarLabel/BarLabelItem';
import { BarLabelPlot } from './BarLabel/BarLabelPlot';
import { checkScaleErrors } from './checkScaleErrors';
import { useBarSeries } from '../hooks/useSeries';

/**
* Solution of the equations
Expand Down Expand Up @@ -87,7 +87,7 @@ const useAggregatedData = (): {
masksData: MaskData[];
} => {
const seriesData =
React.useContext(SeriesContext).bar ??
useBarSeries() ??
({ series: {}, stackingGroups: [], seriesOrder: [] } as FormatterResult<'bar'>);
const axisData = React.useContext(CartesianContext);
const chartId = useChartId();
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/ChartsLegend/ChartsLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { useSlotProps } from '@mui/base/utils';
import { unstable_composeClasses as composeClasses } from '@mui/utils';
import { useThemeProps, useTheme, Theme } from '@mui/material/styles';
import { AnchorPosition, Direction, getSeriesToDisplay } from './utils';
import { SeriesContext } from '../context/SeriesContextProvider';
import { ChartsLegendClasses, getLegendUtilityClass } from './chartsLegendClasses';
import { DefaultizedProps } from '../models/helpers';
import { DefaultChartsLegend, LegendRendererProps } from './DefaultChartsLegend';
import { useDrawingArea } from '../hooks';
import { useSeries } from '../hooks/useSeries';

export interface ChartsLegendSlots {
/**
Expand Down Expand Up @@ -83,7 +83,7 @@ function ChartsLegend(inProps: ChartsLegendProps) {
const classes = useUtilityClasses({ ...props, theme });

const drawingArea = useDrawingArea();
const series = React.useContext(SeriesContext);
const series = useSeries();

const seriesToDisplay = getSeriesToDisplay(series);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { SvgContext } from '../context/DrawingProvider';
import { InteractionContext } from '../context/InteractionProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { SeriesContext } from '../context/SeriesContextProvider';
import { useSeries } from '../hooks/useSeries';
import { useSvgRef } from '../hooks';

type AxisData = {
dataIndex: number;
Expand All @@ -24,8 +24,8 @@ export interface ChartsOnAxisClickHandlerProps {
function ChartsOnAxisClickHandler(props: ChartsOnAxisClickHandlerProps) {
const { onAxisClick } = props;

const svgRef = React.useContext(SvgContext);
const series = React.useContext(SeriesContext);
const svgRef = useSvgRef();
const series = useSeries();
const { axis } = React.useContext(InteractionContext);
const { xAxisIds, xAxis, yAxisIds, yAxis } = React.useContext(CartesianContext);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import { SxProps, Theme } from '@mui/material/styles';
import { useSlotProps } from '@mui/base/utils';
import { AxisInteractionData } from '../context/InteractionProvider';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { ChartSeriesDefaultized, ChartSeriesType } from '../models/seriesType/config';
import { AxisDefaultized } from '../models/axis';
Expand All @@ -12,6 +11,7 @@ import { DefaultChartsAxisTooltipContent } from './DefaultChartsAxisTooltipConte
import { isCartesianSeriesType } from './utils';
import colorGetter from '../internals/colorGetter';
import { ZAxisContext } from '../context/ZAxisContextProvider';
import { useSeries } from '../hooks/useSeries';

type ChartSeriesDefaultizedWithColorGetter = ChartSeriesDefaultized<ChartSeriesType> & {
getColor: (dataIndex: number) => string;
Expand Down Expand Up @@ -61,7 +61,7 @@ function ChartsAxisTooltipContent(props: {

const { xAxisIds, xAxis, yAxisIds, yAxis } = React.useContext(CartesianContext);
const { zAxisIds, zAxis } = React.useContext(ZAxisContext);
const series = React.useContext(SeriesContext);
const series = useSeries();

const USED_AXIS_ID = isXaxis ? xAxisIds[0] : yAxisIds[0];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import PropTypes from 'prop-types';
import { SxProps, Theme } from '@mui/material/styles';
import { useSlotProps } from '@mui/base/utils';
import { ItemInteractionData } from '../context/InteractionProvider';
import { SeriesContext } from '../context/SeriesContextProvider';
import { ChartSeriesDefaultized, ChartSeriesType } from '../models/seriesType/config';
import { ChartsTooltipClasses } from './chartsTooltipClasses';
import { DefaultChartsItemTooltipContent } from './DefaultChartsItemTooltipContent';
import { CartesianContext } from '../context/CartesianContextProvider';
import colorGetter from '../internals/colorGetter';
import { ZAxisContext } from '../context/ZAxisContextProvider';
import { useSeries } from '../hooks/useSeries';

export type ChartsItemContentProps<T extends ChartSeriesType = ChartSeriesType> = {
/**
Expand Down Expand Up @@ -42,9 +42,7 @@ function ChartsItemTooltipContent<T extends ChartSeriesType>(props: {
}) {
const { content, itemData, sx, classes, contentProps } = props;

const series = React.useContext(SeriesContext)[itemData.type]!.series[
itemData.seriesId
] as ChartSeriesDefaultized<T>;
const series = useSeries()[itemData.type]!.series[itemData.seriesId] as ChartSeriesDefaultized<T>;

const { xAxis, yAxis, xAxisIds, yAxisIds } = React.useContext(CartesianContext);
const { zAxis, zAxisIds } = React.useContext(ZAxisContext);
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/ChartsTooltip/utils.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as React from 'react';
import { AxisInteractionData, ItemInteractionData } from '../context/InteractionProvider';
import { SvgContext } from '../context/DrawingProvider';
import {
CartesianChartSeriesType,
ChartSeriesDefaultized,
ChartSeriesType,
} from '../models/seriesType/config';
import { useSvgRef } from '../hooks';

export function generateVirtualElement(mousePosition: { x: number; y: number } | null) {
if (mousePosition === null) {
Expand Down Expand Up @@ -41,7 +41,7 @@ export function generateVirtualElement(mousePosition: { x: number; y: number } |
}

export function useMouseTracker() {
const svgRef = React.useContext(SvgContext);
const svgRef = useSvgRef();

// Use a ref to avoid rerendering on every mousemove event.
const [mousePosition, setMousePosition] = React.useState<null | { x: number; y: number }>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { Delaunay } from 'd3-delaunay';
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
import { InteractionContext } from '../context/InteractionProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { SeriesContext } from '../context/SeriesContextProvider';
import { getValueToPositionMapper } from '../hooks/useScale';
import { getSVGPoint } from '../internals/utils';
import { ScatterItemIdentifier } from '../models';
import { SeriesId } from '../models/seriesType/common';
import { useDrawingArea, useSvgRef } from '../hooks';
import { useHighlighted } from '../context';
import { useScatterSeries } from '../hooks/useSeries';

export type ChartsVoronoiHandlerProps = {
/**
Expand All @@ -35,7 +35,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) {
const { xAxis, yAxis, xAxisIds, yAxisIds } = React.useContext(CartesianContext);
const { dispatch } = React.useContext(InteractionContext);

const { series, seriesOrder } = React.useContext(SeriesContext).scatter ?? {};
const { series, seriesOrder } = useScatterSeries() ?? {};
const voronoiRef = React.useRef<Record<string, VoronoiSeries>>({});
const delauneyRef = React.useRef<Delaunay<any> | undefined>(undefined);

Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/LineChart/AreaPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { area as d3Area } from 'd3-shape';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import {
AreaElement,
Expand All @@ -14,6 +13,7 @@ import getCurveFactory from '../internals/getCurve';
import { DEFAULT_X_AXIS_KEY } from '../constants';
import { LineItemIdentifier } from '../models/seriesType/line';
import { useChartGradient } from '../internals/components/ChartsAxesGradients';
import { useLineSeries } from '../hooks/useSeries';

export interface AreaPlotSlots extends AreaElementSlots {}

Expand All @@ -34,7 +34,7 @@ export interface AreaPlotProps
}

const useAggregatedData = () => {
const seriesData = React.useContext(SeriesContext).line;
const seriesData = useLineSeries();
const axisData = React.useContext(CartesianContext);

if (seriesData === undefined) {
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/LineChart/LineHighlightPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { LineHighlightElement, LineHighlightElementProps } from './LineHighlightElement';
import { getValueToPositionMapper } from '../hooks/useScale';
import { InteractionContext } from '../context/InteractionProvider';
import { DEFAULT_X_AXIS_KEY } from '../constants';
import getColor from './getColor';
import { useLineSeries } from '../hooks/useSeries';

export interface LineHighlightPlotSlots {
lineHighlight?: React.JSXElementConstructor<LineHighlightElementProps>;
Expand Down Expand Up @@ -42,7 +42,7 @@ export interface LineHighlightPlotProps extends React.SVGAttributes<SVGSVGElemen
function LineHighlightPlot(props: LineHighlightPlotProps) {
const { slots, slotProps, ...other } = props;

const seriesData = React.useContext(SeriesContext).line;
const seriesData = useLineSeries();
const axisData = React.useContext(CartesianContext);
const { axis } = React.useContext(InteractionContext);

Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/LineChart/LinePlot.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { line as d3Line } from 'd3-shape';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import {
LineElement,
Expand All @@ -14,6 +13,7 @@ import getCurveFactory from '../internals/getCurve';
import { DEFAULT_X_AXIS_KEY } from '../constants';
import { LineItemIdentifier } from '../models/seriesType/line';
import { useChartGradient } from '../internals/components/ChartsAxesGradients';
import { useLineSeries } from '../hooks/useSeries';

export interface LinePlotSlots extends LineElementSlots {}

Expand All @@ -34,7 +34,7 @@ export interface LinePlotProps
}

const useAggregatedData = () => {
const seriesData = React.useContext(SeriesContext).line;
const seriesData = useLineSeries();
const axisData = React.useContext(CartesianContext);

if (seriesData === undefined) {
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/LineChart/MarkPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import { MarkElement, MarkElementProps } from './MarkElement';
import { getValueToPositionMapper } from '../hooks/useScale';
Expand All @@ -9,6 +8,7 @@ import { DEFAULT_X_AXIS_KEY } from '../constants';
import { LineItemIdentifier } from '../models/seriesType/line';
import { cleanId } from '../internals/utils';
import getColor from './getColor';
import { useLineSeries } from '../hooks/useSeries';

export interface MarkPlotSlots {
mark?: React.JSXElementConstructor<MarkElementProps>;
Expand Down Expand Up @@ -55,7 +55,7 @@ export interface MarkPlotProps
function MarkPlot(props: MarkPlotProps) {
const { slots, slotProps, skipAnimation, onItemClick, ...other } = props;

const seriesData = React.useContext(SeriesContext).line;
const seriesData = useLineSeries();
const axisData = React.useContext(CartesianContext);
const chartId = useChartId();

Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/PieChart/PiePlot.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { SeriesContext } from '../context/SeriesContextProvider';
import { DrawingContext } from '../context/DrawingProvider';
import { PieArcPlot, PieArcPlotProps, PieArcPlotSlotProps, PieArcPlotSlots } from './PieArcPlot';
import { PieArcLabelPlotSlots, PieArcLabelPlotSlotProps, PieArcLabelPlot } from './PieArcLabelPlot';
import { getPercentageValue } from '../internals/utils';
import { getPieCoordinates } from './getPieCoordinates';
import { usePieSeries } from '../hooks/useSeries';

export interface PiePlotSlots extends PieArcPlotSlots, PieArcLabelPlotSlots {}

Expand Down Expand Up @@ -36,7 +36,7 @@ export interface PiePlotProps extends Pick<PieArcPlotProps, 'skipAnimation' | 'o
*/
function PiePlot(props: PiePlotProps) {
const { skipAnimation, slots, slotProps, onItemClick } = props;
const seriesData = React.useContext(SeriesContext).pie;
const seriesData = usePieSeries();
const { left, top, width, height } = React.useContext(DrawingContext);

if (seriesData === undefined) {
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/ScatterChart/ScatterPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { Scatter, ScatterProps } from './Scatter';
import { SeriesContext } from '../context/SeriesContextProvider';
import { CartesianContext } from '../context/CartesianContextProvider';
import getColor from './getColor';
import { ZAxisContext } from '../context/ZAxisContextProvider';
import { useScatterSeries } from '../hooks/useSeries';

export interface ScatterPlotSlots {
scatter?: React.JSXElementConstructor<ScatterProps>;
Expand Down Expand Up @@ -39,7 +39,7 @@ export interface ScatterPlotProps extends Pick<ScatterProps, 'onItemClick'> {
*/
function ScatterPlot(props: ScatterPlotProps) {
const { slots, slotProps, onItemClick } = props;
const seriesData = React.useContext(SeriesContext).scatter;
const seriesData = useScatterSeries();
const axisData = React.useContext(CartesianContext);
const { zAxis, zAxisIds } = React.useContext(ZAxisContext);

Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/context/CartesianContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
} from '../LineChart/extremums';
import { AxisConfig, AxisDefaultized, isBandScaleConfig, isPointScaleConfig } from '../models/axis';
import { getScale } from '../internals/getScale';
import { SeriesContext } from './SeriesContextProvider';
import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../constants';
import {
CartesianChartSeriesType,
Expand All @@ -28,6 +27,7 @@ import { getTickNumber } from '../hooks/useTicks';
import { useDrawingArea } from '../hooks/useDrawingArea';
import { SeriesId } from '../models/seriesType/common';
import { getColorScale, getOrdinalColorScale } from '../internals/colorScale';
import { useSeries } from '../hooks/useSeries';

export type CartesianContextProviderProps = {
/**
Expand Down Expand Up @@ -99,7 +99,7 @@ if (process.env.NODE_ENV !== 'production') {

function CartesianContextProvider(props: CartesianContextProviderProps) {
const { xAxis: inXAxis, yAxis: inYAxis, dataset, children } = props;
const formattedSeries = React.useContext(SeriesContext);
const formattedSeries = useSeries();
const drawingArea = useDrawingArea();

const xAxis = React.useMemo(
Expand Down
12 changes: 10 additions & 2 deletions packages/x-charts/src/context/DrawingProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import useId from '@mui/utils/useId';
import useChartDimensions from '../hooks/useChartDimensions';
import { LayoutConfig } from '../models/layout';
import { Initializable } from './context.types';

export interface DrawingProviderProps extends LayoutConfig {
children: React.ReactNode;
Expand Down Expand Up @@ -59,7 +60,12 @@ if (process.env.NODE_ENV !== 'production') {
DrawingContext.displayName = 'DrawingContext';
}

export const SvgContext = React.createContext<React.RefObject<SVGSVGElement>>({ current: null });
export type SvgContextState = React.RefObject<SVGSVGElement>;

export const SvgContext = React.createContext<Initializable<SvgContextState>>({
isInitialized: false,
data: { current: null },
});

if (process.env.NODE_ENV !== 'production') {
SvgContext.displayName = 'SvgContext';
Expand All @@ -75,8 +81,10 @@ export function DrawingProvider(props: DrawingProviderProps) {
[chartId, drawingArea],
);

const refValue = React.useMemo(() => ({ isInitialized: true, data: svgRef }), [svgRef]);

return (
<SvgContext.Provider value={svgRef}>
<SvgContext.Provider value={refValue}>
<DrawingContext.Provider value={value}>{children}</DrawingContext.Provider>
</SvgContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { SeriesId } from '../../models/seriesType/common';
import { Initializable } from '../context.types';

/**
* The data of the highlighted item.
Expand Down Expand Up @@ -68,12 +69,15 @@ export type HighlightedState = {
isFaded: (input: HighlightItemData) => boolean;
};

export const HighlightedContext = React.createContext<HighlightedState>({
highlightedItem: null,
setHighlighted: () => {},
clearHighlighted: () => {},
isHighlighted: () => false,
isFaded: () => false,
export const HighlightedContext = React.createContext<Initializable<HighlightedState>>({
isInitialized: false,
data: {
highlightedItem: null,
setHighlighted: () => {},
clearHighlighted: () => {},
isHighlighted: () => false,
isFaded: () => false,
},
});

if (process.env.NODE_ENV !== 'production') {
Expand Down
Loading

0 comments on commit 8f0778b

Please sign in to comment.