diff --git a/packages/x-charts/src/ChartsLegend/utils.ts b/packages/x-charts/src/ChartsLegend/utils.ts index a5da75c6985b7..8f57e1077219e 100644 --- a/packages/x-charts/src/ChartsLegend/utils.ts +++ b/packages/x-charts/src/ChartsLegend/utils.ts @@ -12,7 +12,7 @@ export type AnchorPosition = { horizontal: AnchorX; vertical: AnchorY }; export type Direction = 'row' | 'column'; -const legendGetter: { [T in ChartSeriesType]: LegendGetter } = { +const legendGetter: { [T in ChartSeriesType]?: LegendGetter } = { bar: getBarLegend, scatter: getScatterLegend, line: getLineLegend, @@ -21,7 +21,9 @@ const legendGetter: { [T in ChartSeriesType]: LegendGetter } = { export function getSeriesToDisplay(series: FormattedSeries) { return (Object.keys(series) as ChartSeriesType[]).flatMap( - (seriesType: T) => - legendGetter[seriesType as T](series[seriesType as T]!), + (seriesType: T) => { + const getter = legendGetter[seriesType as T]; + return getter === undefined ? [] : getter(series[seriesType as T]!); + }, ); } diff --git a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx index c1d33d29c210e..c275f0a024932 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx @@ -8,7 +8,7 @@ import { ChartSeriesDefaultized, ChartSeriesType } from '../models/seriesType/co import { AxisDefaultized } from '../models/axis'; import { ChartsTooltipClasses } from './chartsTooltipClasses'; import { DefaultChartsAxisTooltipContent } from './DefaultChartsAxisTooltipContent'; -import { isCartesianSeriesType } from './utils'; +import { isCartesianSeriesType } from '../internals/isCartesian'; import colorGetter from '../internals/colorGetter'; import { ZAxisContext } from '../context/ZAxisContextProvider'; import { useSeries } from '../hooks/useSeries'; diff --git a/packages/x-charts/src/ChartsTooltip/DefaultChartsAxisTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/DefaultChartsAxisTooltipContent.tsx index 5cbc62f59c86e..0326ddc472949 100644 --- a/packages/x-charts/src/ChartsTooltip/DefaultChartsAxisTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/DefaultChartsAxisTooltipContent.tsx @@ -10,8 +10,9 @@ import { ChartsTooltipRow, } from './ChartsTooltipTable'; import type { ChartsAxisContentProps } from './ChartsAxisTooltipContent'; -import { isCartesianSeries, utcFormatter } from './utils'; +import { utcFormatter } from './utils'; import { getLabel } from '../internals/getLabel'; +import { isCartesianSeries } from '../internals/isCartesian'; function DefaultChartsAxisTooltipContent(props: ChartsAxisContentProps) { const { series, axis, dataIndex, axisValue, sx, classes } = props; diff --git a/packages/x-charts/src/ChartsTooltip/utils.tsx b/packages/x-charts/src/ChartsTooltip/utils.tsx index 89d86636aefcd..95e2d849abbbf 100644 --- a/packages/x-charts/src/ChartsTooltip/utils.tsx +++ b/packages/x-charts/src/ChartsTooltip/utils.tsx @@ -1,10 +1,6 @@ import * as React from 'react'; import { AxisInteractionData, ItemInteractionData } from '../context/InteractionProvider'; -import { - CartesianChartSeriesType, - ChartSeriesDefaultized, - ChartSeriesType, -} from '../models/seriesType/config'; +import { ChartSeriesType } from '../models/seriesType/config'; import { useSvgRef } from '../hooks'; export function generateVirtualElement(mousePosition: { x: number; y: number } | null) { @@ -95,21 +91,6 @@ export function getTooltipHasData( return hasAxisXData || hasAxisYData; } -export function isCartesianSeriesType(seriesType: string): seriesType is CartesianChartSeriesType { - return ['bar', 'line', 'scatter'].includes(seriesType); -} - -export function isCartesianSeries( - series: ChartSeriesDefaultized & { getColor: (dataIndex: number) => string }, -): series is ChartSeriesDefaultized & { - getColor: (dataIndex: number) => string; -}; -export function isCartesianSeries( - series: ChartSeriesDefaultized, -): series is ChartSeriesDefaultized { - return isCartesianSeriesType(series.type); -} - export function utcFormatter(v: string | number | Date): string { if (v instanceof Date) { return v.toUTCString(); diff --git a/packages/x-charts/src/internals/configInit.ts b/packages/x-charts/src/internals/configInit.ts new file mode 100644 index 0000000000000..228d641b73d67 --- /dev/null +++ b/packages/x-charts/src/internals/configInit.ts @@ -0,0 +1,28 @@ +import { ChartSeriesType } from '../models/seriesType/config'; + +let instance: undefined | Set; + +class CartesianSeriesTypes { + types: Set = new Set(); + + constructor() { + if (instance) { + throw new Error('You can only create one instance!'); + } + instance = this.types; + } + + addType(value: ChartSeriesType) { + this.types.add(value); + } + + getTypes() { + return this.types; + } +} + +export const cartesianSeriesTypes = new CartesianSeriesTypes(); + +cartesianSeriesTypes.addType('bar'); +cartesianSeriesTypes.addType('line'); +cartesianSeriesTypes.addType('scatter'); diff --git a/packages/x-charts/src/internals/index.ts b/packages/x-charts/src/internals/index.ts new file mode 100644 index 0000000000000..b146ce17ee537 --- /dev/null +++ b/packages/x-charts/src/internals/index.ts @@ -0,0 +1 @@ +export * from './configInit'; diff --git a/packages/x-charts/src/internals/isCartesian.ts b/packages/x-charts/src/internals/isCartesian.ts new file mode 100644 index 0000000000000..1b3fb9f19e1ca --- /dev/null +++ b/packages/x-charts/src/internals/isCartesian.ts @@ -0,0 +1,21 @@ +import { + ChartSeriesType, + CartesianChartSeriesType, + ChartSeriesDefaultized, +} from '../models/seriesType/config'; +import { cartesianSeriesTypes } from './configInit'; + +export function isCartesianSeriesType(seriesType: string): seriesType is CartesianChartSeriesType { + return cartesianSeriesTypes.getTypes().has(seriesType as ChartSeriesType); +} + +export function isCartesianSeries( + series: ChartSeriesDefaultized & { getColor: (dataIndex: number) => string }, +): series is ChartSeriesDefaultized & { + getColor: (dataIndex: number) => string; +}; +export function isCartesianSeries( + series: ChartSeriesDefaultized, +): series is ChartSeriesDefaultized { + return isCartesianSeriesType(series.type); +} diff --git a/packages/x-charts/src/models/seriesType/config.ts b/packages/x-charts/src/models/seriesType/config.ts index 608962f6af702..952afd3ee2087 100644 --- a/packages/x-charts/src/models/seriesType/config.ts +++ b/packages/x-charts/src/models/seriesType/config.ts @@ -7,35 +7,64 @@ import { DefaultizedProps, MakeOptional } from '../helpers'; import { StackingGroupsType } from '../../internals/stackSeries'; import { SeriesId } from './common'; -interface ChartsSeriesConfig { +export interface ChartsSeriesConfig { bar: { + /** + * Series type when passed to the formatter (some ids are defaultised to simplify the DX) + */ seriesInput: DefaultizedProps & { color: string }; + /** + * Series type when stored in the context (with all the preprocessing added)) + */ series: DefaultizedBarSeriesType; - canBeStacked: true; + /** + * Series typing such that the one user need to provide + */ + seriesProp: BarSeriesType; itemIdentifier: BarItemIdentifier; + canBeStacked: true; + cartesian: true; }; line: { seriesInput: DefaultizedProps & { color: string }; series: DefaultizedLineSeriesType; - canBeStacked: true; + seriesProp: LineSeriesType; itemIdentifier: LineItemIdentifier; + canBeStacked: true; + cartesian: true; }; scatter: { seriesInput: DefaultizedProps & { color: string }; series: DefaultizedScatterSeriesType; + seriesProp: ScatterSeriesType; itemIdentifier: ScatterItemIdentifier; + cartesian: true; }; pie: { seriesInput: Omit, 'data'> & { data: (MakeOptional & { color: string })[]; }; series: DefaultizedPieSeriesType; + seriesProp: PieSeriesType>; itemIdentifier: PieItemIdentifier; }; } -export type CartesianChartSeriesType = 'bar' | 'line' | 'scatter'; -export type ChartSeriesType = 'bar' | 'line' | 'scatter' | 'pie'; +export type ChartSeriesType = keyof ChartsSeriesConfig; + +export type CartesianChartSeriesType = keyof Pick< + ChartsSeriesConfig, + { + [Key in ChartSeriesType]: ChartsSeriesConfig[Key] extends { cartesian: true } ? Key : never; + }[ChartSeriesType] +>; + +export type StackableChartSeriesType = keyof Pick< + ChartsSeriesConfig, + { + [Key in ChartSeriesType]: ChartsSeriesConfig[Key] extends { canBeStacked: true } ? Key : never; + }[ChartSeriesType] +>; export type ChartSeries = ChartsSeriesConfig[T] extends { canBeStacked: true; diff --git a/packages/x-charts/src/models/seriesType/index.ts b/packages/x-charts/src/models/seriesType/index.ts index c6c848eb91656..70dbfedf195aa 100644 --- a/packages/x-charts/src/models/seriesType/index.ts +++ b/packages/x-charts/src/models/seriesType/index.ts @@ -1,31 +1,29 @@ -import { BarItemIdentifier, BarSeriesType, DefaultizedBarSeriesType } from './bar'; -import { DefaultizedLineSeriesType, LineItemIdentifier, LineSeriesType } from './line'; -import { DefaultizedScatterSeriesType, ScatterItemIdentifier, ScatterSeriesType } from './scatter'; -import { DefaultizedPieSeriesType, PieSeriesType, PieItemIdentifier, PieValueType } from './pie'; -import { MakeOptional } from '../helpers'; +import { BarSeriesType, DefaultizedBarSeriesType } from './bar'; +import { + CartesianChartSeriesType, + ChartSeriesType, + ChartsSeriesConfig, + StackableChartSeriesType, +} from './config'; -type AllSeriesType = - | BarSeriesType - | LineSeriesType - | ScatterSeriesType - | PieSeriesType>; +// Series definition -type CartesianSeriesType = BarSeriesType | LineSeriesType | ScatterSeriesType; +type AllSeriesType = + ChartsSeriesConfig[T]['seriesProp']; -type DefaultizedCartesianSeriesType = - | DefaultizedBarSeriesType - | DefaultizedLineSeriesType - | DefaultizedScatterSeriesType; +type CartesianSeriesType = AllSeriesType; -type DefaultizedSeriesType = DefaultizedCartesianSeriesType | DefaultizedPieSeriesType; +type DefaultizedSeriesType = + ChartsSeriesConfig[T]['series']; -type StackableSeriesType = DefaultizedBarSeriesType | DefaultizedLineSeriesType; +type DefaultizedCartesianSeriesType = DefaultizedSeriesType; -export type SeriesItemIdentifier = - | BarItemIdentifier - | LineItemIdentifier - | ScatterItemIdentifier - | PieItemIdentifier; +type StackableSeriesType = DefaultizedSeriesType; + +// item identifier + +export type SeriesItemIdentifier = + ChartsSeriesConfig[T]['itemIdentifier']; export * from './line'; export * from './bar'; @@ -39,6 +37,8 @@ export type { StackableSeriesType, }; +// Helpers + export function isDefaultizedBarSeries( series: DefaultizedSeriesType, ): series is DefaultizedBarSeriesType {