UNPKG

@mui/x-charts

Version:

The community edition of MUI X Charts components.

214 lines (210 loc) 7.76 kB
'use client'; import { useSeries } from "../hooks/useSeries.mjs"; import { useColorProcessor } from "../internals/plugins/corePlugins/useChartSeries/useColorProcessor.mjs"; import { useStore } from "../internals/store/useStore.mjs"; import { getLabel } from "../internals/getLabel.mjs"; import { utcFormatter } from "./utils.mjs"; import { useRotationAxes, useRotationAxis, useXAxes, useXAxis, useYAxes, useYAxis } from "../hooks/useAxis.mjs"; import { useZAxes } from "../hooks/useZAxis.mjs"; import { selectorChartsInteractionTooltipXAxes, selectorChartsInteractionTooltipYAxes } from "../internals/plugins/featurePlugins/useChartCartesianAxis/index.mjs"; import { selectorChartsInteractionTooltipRotationAxes } from "../internals/plugins/featurePlugins/useChartPolarAxis/useChartPolarInteraction.selectors.mjs"; import { isPolarSeriesType } from "../internals/isPolar.mjs"; import { selectorIsItemVisibleGetter } from "../internals/plugins/featurePlugins/useChartVisibilityManager/useChartVisibilityManager.selectors.mjs"; import { composableCartesianSeriesTypes } from "../models/seriesType/composition.mjs"; function defaultAxisTooltipConfig(axis, dataIndex, axisDirection) { const axisValue = axis.data?.[dataIndex] ?? null; const axisFormatter = axis.valueFormatter ?? (v => axis.scaleType === 'utc' ? utcFormatter(v) : v.toLocaleString()); const axisFormattedValue = axisFormatter(axisValue, { location: 'tooltip', scale: axis.scale }); return { axisDirection, axisId: axis.id, mainAxis: axis, dataIndex, axisValue, axisFormattedValue, seriesItems: [] }; } /** * Returns the axes to display in the tooltip and the series item related to them. */ export function useAxesTooltip(params) { const { directions } = params ?? {}; const defaultXAxis = useXAxis(); const defaultYAxis = useYAxis(); const defaultRotationAxis = useRotationAxis(); const store = useStore(); const tooltipXAxes = store.use(selectorChartsInteractionTooltipXAxes); const tooltipYAxes = store.use(selectorChartsInteractionTooltipYAxes); const tooltipRotationAxes = store.use(selectorChartsInteractionTooltipRotationAxes); const series = useSeries(); const { xAxis } = useXAxes(); const { yAxis } = useYAxes(); const { zAxis, zAxisIds } = useZAxes(); const { rotationAxis } = useRotationAxes(); const colorProcessors = useColorProcessor(); const isItemVisible = store.use(selectorIsItemVisibleGetter); if (tooltipXAxes.length === 0 && tooltipYAxes.length === 0 && tooltipRotationAxes.length === 0) { return null; } const tooltipAxes = []; if (directions === undefined || directions.includes('x')) { tooltipXAxes.forEach(({ axisId, dataIndex }) => { tooltipAxes.push(defaultAxisTooltipConfig(xAxis[axisId], dataIndex, 'x')); }); } if (directions === undefined || directions.includes('y')) { tooltipYAxes.forEach(({ axisId, dataIndex }) => { tooltipAxes.push(defaultAxisTooltipConfig(yAxis[axisId], dataIndex, 'y')); }); } if (directions === undefined || directions.includes('rotation')) { tooltipRotationAxes.forEach(({ axisId, dataIndex }) => { tooltipAxes.push(defaultAxisTooltipConfig(rotationAxis[axisId], dataIndex, 'rotation')); }); } Object.keys(series).filter(seriesType => composableCartesianSeriesTypes.has(seriesType)).forEach(seriesType => { 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 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; let formattedValue; if (seriesType === 'ohlc' && Array.isArray(rawValue)) { const [open, high, low, close] = rawValue; const formatter = seriesToAdd.valueFormatter; 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(rawValue, { dataIndex }); } tooltipAxes[tooltipItemIndex].seriesItems.push({ seriesId, color, value, formattedValue, formattedLabel, markType: seriesToAdd.labelMarkType, markShape: 'showMark' in seriesToAdd && seriesToAdd.showMark ? seriesToAdd.shape ?? 'circle' : undefined }); } }); }); Object.keys(series).filter(isPolarSeriesType).forEach(seriesType => { 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 providedRotationAxisId = // @ts-expect-error Should be fixed when we introduce a polar series with a rotationAxisId seriesToAdd.rotationAxisId ?? defaultRotationAxis?.id; const tooltipItemIndex = tooltipAxes.findIndex(({ axisDirection, axisId }) => axisDirection === 'rotation' && axisId === providedRotationAxisId); // Test if the series uses the default axis if (tooltipItemIndex >= 0) { const { dataIndex } = tooltipAxes[tooltipItemIndex]; const color = colorProcessors[seriesType]?.(seriesToAdd)(dataIndex) ?? ''; const value = seriesToAdd.data[dataIndex] ?? null; const formattedValue = seriesToAdd.valueFormatter(value, { dataIndex }); const formattedLabel = getLabel(seriesToAdd.label, 'tooltip') ?? null; tooltipAxes[tooltipItemIndex].seriesItems.push({ seriesId, color, value, formattedValue, formattedLabel, markType: seriesToAdd.labelMarkType, markShape: 'showMark' in seriesToAdd && seriesToAdd.showMark ? 'circle' : undefined }); } }); }); return tooltipAxes; }