Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const selectorReturnNull = () => null;

function getIsOpenSelector(
trigger: TriggerOptions,
axisSystem: 'none' | 'polar' | 'cartesian',
axisSystem: 'none' | 'radial' | 'cartesian',
shouldPreventBecauseOfBrush?: boolean,
) {
if (shouldPreventBecauseOfBrush) {
Expand All @@ -46,7 +46,7 @@ function getIsOpenSelector(
if (trigger === 'item') {
return selectorChartsTooltipItemIsDefined;
}
if (axisSystem === 'polar') {
if (axisSystem === 'radial') {
return selectorChartsInteractionPolarAxisTooltip;
}
if (axisSystem === 'cartesian') {
Expand Down
153 changes: 82 additions & 71 deletions packages/x-charts/src/ChartsTooltip/useAxesTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useSeries } from '../hooks/useSeries';
import { useColorProcessor } from '../internals/plugins/corePlugins/useChartSeries/useColorProcessor';
import { type SeriesId } from '../models/seriesType/common';
import {
type ChartSeriesDefaultized,
type CartesianChartSeriesType,
type ChartsSeriesConfig,
type PolarChartSeriesType,
Expand Down Expand Up @@ -33,6 +34,7 @@ import {
type ComposableCartesianChartSeriesType,
composableCartesianSeriesTypes,
} from '../models/seriesType/composition';
import type { ProcessedSeries } from '../internals/plugins/corePlugins/useChartSeries/useChartSeries.types';

export interface UseAxesTooltipReturnValue<
SeriesType extends CartesianChartSeriesType | PolarChartSeriesType =
Expand Down Expand Up @@ -156,82 +158,92 @@ export function useAxesTooltip<
});
}

Object.keys(series)
.filter((seriesType): seriesType is ComposableCartesianChartSeriesType =>
composableCartesianSeriesTypes.has(seriesType as ComposableCartesianChartSeriesType),
)
.forEach(<Type extends ComposableCartesianChartSeriesType>(seriesType: Type) => {
const seriesOfType = series[seriesType];
if (!seriesOfType) {
return [];
}
return seriesOfType.seriesOrder.forEach((seriesId) => {
const seriesToAdd = seriesOfType.series[seriesId]!;

// Skip hidden series (only if visibility manager is available)
if (isItemVisible && !isItemVisible({ type: seriesType, seriesId })) {
return;
const isCartesianContext = xAxis !== undefined || yAxis !== undefined;

if (isCartesianContext) {
Object.keys(series)
.filter((seriesType): seriesType is ComposableCartesianChartSeriesType =>
composableCartesianSeriesTypes.has(seriesType as ComposableCartesianChartSeriesType),
)
.forEach(<Type extends ComposableCartesianChartSeriesType>(seriesType: Type) => {
const seriesOfType = series[seriesType] as ProcessedSeries<Type, 'cartesian'>[Type];
if (!seriesOfType) {
return [];
}
return seriesOfType.seriesOrder.forEach((seriesId) => {
const seriesToAdd = seriesOfType.series[seriesId] as ChartSeriesDefaultized<
Type,
'cartesian'
>;

// Skip hidden series (only if visibility manager is available)
if (isItemVisible && !isItemVisible({ type: seriesType, seriesId })) {
return;
}

const providedXAxisId = seriesToAdd.xAxisId ?? defaultXAxis.id;
const providedYAxisId = seriesToAdd.yAxisId ?? defaultYAxis.id;

const tooltipItemIndex = tooltipAxes.findIndex(
({ axisDirection, axisId }) =>
(axisDirection === 'x' && axisId === providedXAxisId) ||
(axisDirection === 'y' && axisId === providedYAxisId),
);
// Test if the series uses the default axis
if (tooltipItemIndex >= 0) {
const zAxisId = 'zAxisId' in seriesToAdd ? seriesToAdd.zAxisId : zAxisIds[0];
const { dataIndex } = tooltipAxes[tooltipItemIndex];
const color =
colorProcessors[seriesType]?.(
seriesToAdd,
xAxis[providedXAxisId],
yAxis[providedYAxisId],
zAxisId ? zAxis[zAxisId] : undefined,
)(dataIndex) ?? '';

const rawValue = seriesToAdd.data[dataIndex] ?? null;
const formattedLabel = getLabel(seriesToAdd.label, 'tooltip') ?? null;

let value: any;
let formattedValue: any;

if (seriesType === 'ohlc' && Array.isArray(rawValue)) {
const [open, high, low, close] = rawValue as [number, number, number, number];
const formatter = seriesToAdd.valueFormatter as any;
value = { open, high, low, close };
formattedValue = {
open: formatter(open, { dataIndex, field: 'open' }),
high: formatter(high, { dataIndex, field: 'high' }),
low: formatter(low, { dataIndex, field: 'low' }),
close: formatter(close, { dataIndex, field: 'close' }),
};
} else {
value = rawValue;
formattedValue = (seriesToAdd.valueFormatter as any)(rawValue, {
dataIndex,
const providedXAxisId = seriesToAdd.xAxisId ?? defaultXAxis.id;
const providedYAxisId = seriesToAdd.yAxisId ?? defaultYAxis.id;

const tooltipItemIndex = tooltipAxes.findIndex(
({ axisDirection, axisId }) =>
(axisDirection === 'x' && axisId === providedXAxisId) ||
(axisDirection === 'y' && axisId === providedYAxisId),
);
// Test if the series uses the default axis
if (tooltipItemIndex >= 0) {
const zAxisId = 'zAxisId' in seriesToAdd ? seriesToAdd.zAxisId : zAxisIds[0];
const { dataIndex } = tooltipAxes[tooltipItemIndex];
const color =
colorProcessors[seriesType]?.(
seriesToAdd,
xAxis[providedXAxisId],
yAxis[providedYAxisId],
zAxisId ? zAxis[zAxisId] : undefined,
)(dataIndex) ?? '';

const rawValue = seriesToAdd.data[dataIndex] ?? null;
const formattedLabel = getLabel(seriesToAdd.label, 'tooltip') ?? null;

let value: any;
let formattedValue: any;

if (seriesType === 'ohlc' && Array.isArray(rawValue)) {
const [open, high, low, close] = rawValue as [number, number, number, number];
const formatter = seriesToAdd.valueFormatter as any;
value = { open, high, low, close };
formattedValue = {
open: formatter(open, { dataIndex, field: 'open' }),
high: formatter(high, { dataIndex, field: 'high' }),
low: formatter(low, { dataIndex, field: 'low' }),
close: formatter(close, { dataIndex, field: 'close' }),
};
} else {
value = rawValue;
formattedValue = (seriesToAdd.valueFormatter as any)(rawValue, {
dataIndex,
});
}

tooltipAxes[tooltipItemIndex].seriesItems.push({
seriesId,
color,
value,
formattedValue,
formattedLabel,
markType: seriesToAdd.labelMarkType,
markShape:
'showMark' in seriesToAdd && seriesToAdd.showMark
? (seriesToAdd.shape ?? 'circle')
: undefined,
});
}

tooltipAxes[tooltipItemIndex].seriesItems.push({
seriesId,
color,
value,
formattedValue,
formattedLabel,
markType: seriesToAdd.labelMarkType,
markShape:
'showMark' in seriesToAdd && seriesToAdd.showMark
? (seriesToAdd.shape ?? 'circle')
: undefined,
});
}
});
});
});

return tooltipAxes as UseAxesTooltipReturnValue<SeriesType>[];
}

// For polar charts
Object.keys(series)
.filter(isPolarSeriesType)
.forEach(<Type extends PolarChartSeriesType>(seriesType: Type) => {
Expand Down Expand Up @@ -278,6 +290,5 @@ export function useAxesTooltip<
}
});
});

return tooltipAxes as UseAxesTooltipReturnValue<SeriesType>[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ export default function getItemAtPosition(

const { axis: xAxes, axisIds: xAxisIds } = selectorChartXAxis(state);
const { axis: yAxes, axisIds: yAxisIds } = selectorChartYAxis(state);
const series = selectorAllSeriesOfType(state, 'line') as ProcessedSeries['line'];
const series = selectorAllSeriesOfType(state, 'line') as ProcessedSeries<
'line',
'cartesian'
>['line'];

if (!series || series.seriesOrder.length === 0) {
return undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/LineChart/seriesConfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '../../internals/plugins/featurePlugins/useChartHighlight';
import descriptionGetter from './descriptionGetter';

export const lineSeriesConfig: ChartSeriesTypeConfig<'line'> = {
export const lineSeriesConfig: ChartSeriesTypeConfig<'line', 'cartesian'> = {
colorProcessor: getColor,
seriesProcessor,
legendGetter,
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/LineChart/seriesConfig/tooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {
TooltipGetter,
} from '../../internals/plugins/corePlugins/useChartSeriesConfig';

const tooltipGetter: TooltipGetter<'line'> = (params) => {
const tooltipGetter: TooltipGetter<'line', 'cartesian'> = (params) => {
const { series, getColor, identifier } = params;

if (!identifier || identifier.dataIndex === undefined) {
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts/src/hooks/useAxisSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { useStore } from '../internals/store/useStore';
* The hook assumes polar and cartesian are never implemented at the same time.
* @returns The coordinate system
*/
export function useAxisSystem(): 'none' | 'polar' | 'cartesian' {
export function useAxisSystem(): 'none' | 'radial' | 'cartesian' {
const store = useStore<[UseChartPolarAxisSignature]>();
const rawRotationAxis = store.use(selectorChartRawRotationAxis);
const rawXAxis = store.use(selectorChartRawXAxis);

if (rawRotationAxis !== undefined) {
return 'polar';
return 'radial';
}
if (rawXAxis !== undefined) {
return 'cartesian';
Expand Down
22 changes: 16 additions & 6 deletions packages/x-charts/src/hooks/useLineSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,39 @@ import { type SeriesId } from '../models/seriesType/common';
import { type ChartSeriesDefaultized } from '../models/seriesType/config';
import { useSeriesOfType, useAllSeriesOfType } from '../internals/seriesSelectorOfType';

export type UseLineSeriesReturnValue = ChartSeriesDefaultized<'line'>;
export type UseLineSeriesContextReturnValue = ProcessedSeries['line'];
export type UseLineSeriesReturnValue<AxisType extends 'cartesian' | 'radial'> =
ChartSeriesDefaultized<'line', AxisType>;
export type UseLineSeriesContextReturnValue<AxisType extends 'cartesian' | 'radial'> =
ProcessedSeries<'line', AxisType>['line'];

/**
* Get access to the internal state of line series.
*
* @param {SeriesId} seriesId The id of the series to get.
* @returns {UseLineSeriesReturnValue} the line series
*/
export function useLineSeries(seriesId: SeriesId): UseLineSeriesReturnValue | undefined;
export function useLineSeries<AxisType extends 'cartesian' | 'radial' = 'cartesian'>(
seriesId: SeriesId,
): UseLineSeriesReturnValue<AxisType> | undefined;
/**
* Get access to the internal state of line series.
*
* When called without arguments, it returns all line series.
*
* @returns {UseLineSeriesReturnValue[]} the line series
*/
export function useLineSeries(): UseLineSeriesReturnValue[];
export function useLineSeries<
AxisType extends 'cartesian' | 'radial' = 'cartesian',
>(): UseLineSeriesReturnValue<AxisType>[];
/**
* Get access to the internal state of line series.
*
* @param {SeriesId[]} seriesIds The ids of the series to get. Order is preserved.
* @returns {UseLineSeriesReturnValue[]} the line series
*/
export function useLineSeries(seriesIds: SeriesId[]): UseLineSeriesReturnValue[];
export function useLineSeries<AxisType extends 'cartesian' | 'radial' = 'cartesian'>(
seriesIds: SeriesId[],
): UseLineSeriesReturnValue<AxisType>[];
export function useLineSeries(seriesIds?: SeriesId | SeriesId[]) {
return useSeriesOfType('line', seriesIds);
}
Expand All @@ -41,6 +49,8 @@ export function useLineSeries(seriesIds?: SeriesId | SeriesId[]) {
* - stackingGroups: the array of stacking groups. Each group contains the series ids stacked and the strategy to use.
* @returns the line series
*/
export function useLineSeriesContext(): UseLineSeriesContextReturnValue {
export function useLineSeriesContext<
AxisType extends 'cartesian' | 'radial' = 'cartesian',
>(): UseLineSeriesContextReturnValue<AxisType> {
return useAllSeriesOfType('line');
}
1 change: 1 addition & 0 deletions packages/x-charts/src/internals/configInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@ cartesianSeriesTypes.addType('scatter');
export const polarSeriesTypes = new PolarSeriesTypes();

polarSeriesTypes.addType('radar');
polarSeriesTypes.addType('line');
2 changes: 1 addition & 1 deletion packages/x-charts/src/internals/isCartesian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ export function isCartesianSeriesType(seriesType: string): seriesType is Cartesi

export function isCartesianSeries(
series: ChartSeriesDefaultized<ChartSeriesType>,
): series is ChartSeriesDefaultized<CartesianChartSeriesType> {
): series is ChartSeriesDefaultized<CartesianChartSeriesType, 'cartesian'> {
return isCartesianSeriesType(series.type);
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ export type UseChartSeriesDefaultizedParameters<
theme: 'light' | 'dark';
};

export type ProcessedSeries<SeriesType extends ChartSeriesType = ChartSeriesType> = {
[type in SeriesType]?: SeriesProcessorResult<type>;
export type ProcessedSeries<
SeriesType extends ChartSeriesType = ChartSeriesType,
AxisType extends 'cartesian' | 'radial' = any,
> = {
[type in SeriesType]?: SeriesProcessorResult<type, AxisType>;
};

export type SeriesLayout<SeriesType extends ChartSeriesType = ChartSeriesType> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { AxisConfig, AxisId } from '../../../../../models/axis';
import type { SeriesId } from '../../../../../models/seriesType/common';

type CartesianExtremumGetterParams<SeriesType extends CartesianChartSeriesType> = {
series: Record<SeriesId, ChartSeriesDefaultized<SeriesType>>;
series: Record<SeriesId, ChartSeriesDefaultized<SeriesType, 'cartesian'>>;
axis: AxisConfig;
axisIndex: number;
isDefaultAxis: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import type { ChartState } from '../../../models/chart';
import type { ChartSeriesType } from '../../../../../models/seriesType/config';
import type { ChartSeriesTypeRequiredPlugins } from './seriesConfig.types';

export type GetItemAtPosition<SeriesType extends ChartSeriesType> = (
state: ChartState<ChartSeriesTypeRequiredPlugins<SeriesType>>,
export type GetItemAtPosition<
SeriesType extends ChartSeriesType,
AxisType extends 'cartesian' | 'radial',
> = (
state: ChartState<ChartSeriesTypeRequiredPlugins<SeriesType, AxisType>>,
point: { x: number; y: number },
) => SeriesItemIdentifierWithType<SeriesType> | undefined;
Loading
Loading