diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.test.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.test.tsx index d7d0720670214..1bef9c67f750b 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.test.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.test.tsx @@ -23,4 +23,55 @@ describe(' - License', () => { expect(await screen.findAllByText('MUI X Missing license key')).not.to.equal(null); }); + + it('should render "No data to display" when axes are empty arrays', () => { + render(); + + expect(screen.getByText('No data to display')).toBeVisible(); + }); + + describe('axis defaults', () => { + const series = [ + { + data: [ + [0, 3, 7], + [1, 5, 8], + ], + }, + ] as const; + + it('should render default axes when axes are empty arrays and series contain data', () => { + render(); + + const xAxisTickLabels = screen.getAllByTestId('ChartsXAxisTickLabel'); + expect(xAxisTickLabels.map((t) => t.textContent)).to.deep.equal(['0', '1']); + + const yAxisTickLabels = screen.getAllByTestId('ChartsYAxisTickLabel'); + expect(yAxisTickLabels.map((t) => t.textContent)).to.deep.equal([ + '0', + '1', + '2', + '3', + '4', + '5', + ]); + }); + + it('should render default axes when axes are an array of an empty object and series contain data', () => { + render(); + + const xAxisTickLabels = screen.getAllByTestId('ChartsXAxisTickLabel'); + expect(xAxisTickLabels.map((t) => t.textContent)).to.deep.equal(['0', '1']); + + const yAxisTickLabels = screen.getAllByTestId('ChartsYAxisTickLabel'); + expect(yAxisTickLabels.map((t) => t.textContent)).to.deep.equal([ + '0', + '1', + '2', + '3', + '4', + '5', + ]); + }); + }); }); diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index f15ea4db71190..0d89fb7040187 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -22,6 +22,7 @@ import { ChartsOverlaySlotProps, ChartsOverlaySlots, } from '@mui/x-charts/ChartsOverlay'; +import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '@mui/x-charts/constants'; import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro'; import { HeatmapSeriesType } from '../models/seriesType/heatmap'; import { HeatmapPlot } from './HeatmapPlot'; @@ -100,6 +101,19 @@ const defaultColorMap = interpolateRgbBasis([ const seriesConfig: ChartSeriesConfig<'heatmap'> = { heatmap: heatmapSeriesConfig }; +function getDefaultDataForAxis(series: HeatmapProps['series'], dimension: number) { + if (series?.[0]?.data === undefined || series[0].data.length === 0) { + return []; + } + + return Array.from( + { length: Math.max(...series[0].data.map((dataPoint) => dataPoint[dimension])) + 1 }, + (_, index) => index, + ); +} +const getDefaultDataForXAxis = (series: HeatmapProps['series']) => getDefaultDataForAxis(series, 0); +const getDefaultDataForYAxis = (series: HeatmapProps['series']) => getDefaultDataForAxis(series, 1); + const Heatmap = React.forwardRef(function Heatmap( inProps: HeatmapProps, ref: React.Ref, @@ -129,13 +143,25 @@ const Heatmap = React.forwardRef(function Heatmap( const clipPathId = `${id}-clip-path`; const defaultizedXAxis = React.useMemo( - () => xAxis.map((axis) => ({ scaleType: 'band' as const, categoryGapRatio: 0, ...axis })), - [xAxis], + () => + (xAxis && xAxis.length > 0 ? xAxis : [{ id: DEFAULT_X_AXIS_KEY }]).map((axis) => ({ + scaleType: 'band' as const, + categoryGapRatio: 0, + ...axis, + data: axis.data ?? getDefaultDataForXAxis(series), + })), + [series, xAxis], ); const defaultizedYAxis = React.useMemo( - () => yAxis.map((axis) => ({ scaleType: 'band' as const, categoryGapRatio: 0, ...axis })), - [yAxis], + () => + (yAxis && yAxis.length > 0 ? yAxis : [{ id: DEFAULT_Y_AXIS_KEY }]).map((axis) => ({ + scaleType: 'band' as const, + categoryGapRatio: 0, + ...axis, + data: axis.data ?? getDefaultDataForYAxis(series), + })), + [series, yAxis], ); const defaultizedZAxis = React.useMemo( diff --git a/packages/x-charts/src/BarChart/BarChart.test.tsx b/packages/x-charts/src/BarChart/BarChart.test.tsx index 8f598d3d21d89..652d158145322 100644 --- a/packages/x-charts/src/BarChart/BarChart.test.tsx +++ b/packages/x-charts/src/BarChart/BarChart.test.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils/createRenderer'; import { describeConformance } from 'test/utils/describeConformance'; import { BarChart } from '@mui/x-charts/BarChart'; +import { expect } from 'chai'; +import { screen } from '@mui/internal-test-utils'; describe('', () => { const { render } = createRenderer(); @@ -28,4 +30,10 @@ describe('', () => { ], }), ); + + it('should render "No data to display" when axes are empty arrays', () => { + render(); + + expect(screen.getByText('No data to display')).toBeVisible(); + }); }); diff --git a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx index de7cb706cb5f6..1c25d3252377d 100644 --- a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx +++ b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx @@ -278,6 +278,7 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { diff --git a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx index fa71cd0029be0..3719764e2bb6f 100644 --- a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx +++ b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx @@ -208,6 +208,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { diff --git a/packages/x-charts/src/LineChart/LineChart.test.tsx b/packages/x-charts/src/LineChart/LineChart.test.tsx index 441d32c31e96c..8cf1e45c8684d 100644 --- a/packages/x-charts/src/LineChart/LineChart.test.tsx +++ b/packages/x-charts/src/LineChart/LineChart.test.tsx @@ -2,6 +2,8 @@ import * as React from 'react'; import { createRenderer } from '@mui/internal-test-utils/createRenderer'; import { describeConformance } from 'test/utils/describeConformance'; import { LineChart } from '@mui/x-charts/LineChart'; +import { expect } from 'chai'; +import { screen } from '@mui/internal-test-utils'; describe('', () => { const { render } = createRenderer(); @@ -27,4 +29,10 @@ describe('', () => { ], }), ); + + it('should render "No data to display" when axes are empty arrays', () => { + render(); + + expect(screen.getByText('No data to display')).toBeVisible(); + }); }); diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.test.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.test.tsx index 732a19fa566aa..0cc6fbddc68f3 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.test.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.test.tsx @@ -159,4 +159,10 @@ describe('', () => { const labelY = await screen.findByText('600'); expect(labelY).toBeVisible(); }); + + it('should render "No data to display" when axes are empty arrays', () => { + render(); + + expect(screen.getByText('No data to display')).toBeVisible(); + }); }); diff --git a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts index f357a6f2dfdba..5f299698a1922 100644 --- a/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts +++ b/packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/defaultizeAxis.ts @@ -26,9 +26,6 @@ export function defaultizeAxis( ): AxisConfig[] { const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY; - const hasNoDefaultAxis = - inAxis === undefined || inAxis.findIndex(({ id }) => id === DEFAULT_AXIS_KEY) === -1; - const offsets = { top: 0, right: 0, @@ -37,10 +34,10 @@ export function defaultizeAxis( none: 0, }; - const parsedAxes = [ - ...(inAxis ?? []), - ...(hasNoDefaultAxis ? [{ id: DEFAULT_AXIS_KEY, scaleType: 'linear' as const }] : []), - ].map((axisConfig, index) => { + const inputAxes = + inAxis && inAxis.length > 0 ? inAxis : [{ id: DEFAULT_AXIS_KEY, scaleType: 'linear' as const }]; + + const parsedAxes = inputAxes.map((axisConfig, index) => { const dataKey = axisConfig.dataKey; const defaultPosition = axisName === 'x' ? ('bottom' as const) : ('left' as const);