Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[charts] Readonly array inputs #16632

Merged
merged 9 commits into from
Feb 18, 2025
Merged
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
2 changes: 1 addition & 1 deletion docs/pages/x/api/charts/axis-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"colorMap": {
"type": { "description": "OrdinalColorConfig | ContinuousColorConfig | PiecewiseColorConfig" }
},
"data": { "type": { "description": "V[]" } },
"data": { "type": { "description": "readonly V[]" } },
"dataKey": { "type": { "description": "string" } },
"domainLimit": {
"type": {
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/x/api/charts/bar-series-type.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"properties": {
"type": { "type": { "description": "'bar'" }, "required": true },
"color": { "type": { "description": "string" } },
"data": { "type": { "description": "(number | null)[]" } },
"data": { "type": { "description": "readonly (number | null)[]" } },
"dataKey": { "type": { "description": "string" } },
"highlightScope": { "type": { "description": "Partial<HighlightScope>" } },
"id": { "type": { "description": "SeriesId" } },
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/x/api/charts/line-series-type.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"color": { "type": { "description": "string" } },
"connectNulls": { "type": { "description": "boolean" }, "default": "false" },
"curve": { "type": { "description": "CurveType" }, "default": "'monotoneX'" },
"data": { "type": { "description": "(number | null)[]" } },
"data": { "type": { "description": "readonly (number | null)[]" } },
"dataKey": { "type": { "description": "string" } },
"disableHighlight": { "type": { "description": "boolean" }, "default": "false" },
"highlightScope": { "type": { "description": "Partial<HighlightScope>" } },
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/x/api/charts/scatter-series-type.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"properties": {
"type": { "type": { "description": "'scatter'" }, "required": true },
"color": { "type": { "description": "string" } },
"data": { "type": { "description": "ScatterValueType[]" } },
"data": { "type": { "description": "readonly ScatterValueType[]" } },
"datasetKeys": {
"type": {
"description": "{<br /> /**<br /> * The key used to retrieve data from the dataset for the X axis.<br /> */<br /> x: string<br /> /**<br /> * The key used to retrieve data from the dataset for the Y axis.<br /> */<br /> y: string<br /> /**<br /> * The key used to retrieve data from the dataset for the Z axis.<br /> */<br /> z?: string<br /> /**<br /> * The key used to retrieve data from the dataset for the id.<br /> */<br /> id?: string<br />}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const useChartProZoom: ChartPlugin<UseChartProZoomSignature> = ({
(zoomData: ZoomData[] | ((prev: ZoomData[]) => ZoomData[])) => {
store.update((prevState) => {
const newZoomData =
typeof zoomData === 'function' ? zoomData(prevState.zoom.zoomData) : zoomData;
typeof zoomData === 'function' ? zoomData([...prevState.zoom.zoomData]) : zoomData;
onZoomChange?.(newZoomData);

if (prevState.zoom.isControlled) {
Expand Down Expand Up @@ -136,7 +136,11 @@ export const useChartProZoom: ChartPlugin<UseChartProZoomSignature> = ({
);

const isDraggingRef = React.useRef(false);
const touchStartRef = React.useRef<{ x: number; y: number; zoomData: ZoomData[] } | null>(null);
const touchStartRef = React.useRef<{
x: number;
y: number;
zoomData: readonly ZoomData[];
} | null>(null);
React.useEffect(() => {
const element = svgRef.current;
if (element === null || !isPanEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ export interface UseChartProZoomParameters {
* The list of zoom data related to each axis.
* Used to initialize the zoom in a specific configuration without controlling it.
*/
initialZoom?: ZoomData[];
initialZoom?: readonly ZoomData[];
/**
* Callback fired when the zoom has changed.
*
* @param {ZoomData[]} zoomData Updated zoom data.
*/
onZoomChange?: (zoomData: ZoomData[] | ((zoomData: ZoomData[]) => ZoomData[])) => void;
onZoomChange?: (zoomData: ZoomData[]) => void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't zoomData here also be readonly? We probably don't want users pushing to this array, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, yes, but I didn't want to introduce a breaking change with this 😩

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense 👍

Isn't now the best time to do it? Or is the performance hit preferable to causing a breaking change? Still trying to understand where we should place the line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now there is no performance hit, I've removed the destructuring changes by making the internal state also immutable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I should have linked the line I was referring to.

I was referring to line 106 on useChartProZoom. We're now creating a new array where we weren't before.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, true, but that specific case shouldn't really affect us much. zoomData is not meant to be a super long array.

/**
* The list of zoom data related to each axis.
*/
zoomData?: ZoomData[];
zoomData?: readonly ZoomData[];
}

export type UseChartProZoomDefaultizedParameters = UseChartProZoomParameters &
Expand All @@ -37,7 +37,7 @@ export interface UseChartProZoomState {
/**
* Mapping of axis id to the zoom data.
*/
zoomData: ZoomData[];
zoomData: readonly ZoomData[];
/**
* Internal information to know if the user control the state or not.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts-pro/src/models/seriesType/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface HeatmapSeriesType
/**
* Data associated to each bar.
*/
data?: HeatmapValueType[];
data?: readonly HeatmapValueType[];
/**
* The key used to retrieve data from the dataset.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/BarChart/checkClickEvent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const config = {
margin: { top: 0, left: 0, bottom: 0, right: 0 },
width: 400,
height: 400,
};
} as const;

// Plot as follow to simplify click position
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const config: Partial<BarChartProps> = {
hideLegend: true,
width: 400,
height: 400,
};
} as const;

// Plot as follow to simplify click position
//
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/LineChart/checkClickEvent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const config = {
margin: { top: 0, left: 0, bottom: 0, right: 0 },
width: 400,
height: 400,
};
} as const;

describe('LineChart - click event', () => {
const { render } = createRenderer();
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/LineChart/seriesConfig/extremums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type GetValues = (d: [number, number]) => [number, number];

function getSeriesExtremums(
getValues: GetValues,
data: (number | null)[],
data: readonly (number | null)[],
stackedData: [number, number][],
filter?: CartesianExtremumFilter,
): [number, number] {
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/PieChart/checkClickEvent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { PieChart } from '@mui/x-charts/PieChart';
const config = {
width: 400,
height: 400,
};
} as const;

describe('PieChart - click event', () => {
const { render } = createRenderer();
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/ScatterChart/ScatterChart.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('<ScatterChart />', () => {
margin: { top: 0, left: 0, bottom: 0, right: 0 },
width: 100,
height: 100,
};
} as const;

// svg.createSVGPoint not supported by JSDom https://github.com/jsdom/jsdom/issues/300
testSkipIf(isJSDOM)('should show the tooltip without errors in default config', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const config = {
margin: { top: 0, left: 0, bottom: 0, right: 0 },
width: 100,
height: 100,
};
} as const;

// Plot on series as a dice 5
//
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/context/PolarProvider/Polar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type PolarProviderProps = {
/**
* An array of objects that can be used to populate series and axes data using their `dataKey` property.
*/
dataset?: DatasetType;
dataset?: Readonly<DatasetType>;
children: React.ReactNode;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ export const preprocessSeries = <TSeriesType extends ChartSeriesType>({
seriesConfig,
dataset,
}: {
series: AllSeriesType<TSeriesType>[];
series: readonly AllSeriesType<TSeriesType>[];
colors: string[];
seriesConfig: ChartSeriesConfig<TSeriesType>;
dataset?: DatasetType;
dataset?: Readonly<DatasetType>;
}) => {
// Group series by type
const seriesGroups: { [type in ChartSeriesType]?: SeriesProcessorParams<type> } = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ useChartSeries.params = {
const EMPTY_ARRAY: any[] = [];

useChartSeries.getDefaultizedParams = ({ params }) => ({
series: EMPTY_ARRAY,
...params,
series: params.series?.length ? params.series : EMPTY_ARRAY,
colors: params.colors ?? rainbowSurgePalette,
theme: params.theme ?? 'light',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ export interface UseChartSeriesParameters<T extends ChartSeriesType = ChartSerie
/**
* An array of objects that can be used to populate series and axes data using their `dataKey` property.
*/
dataset?: DatasetType;
dataset?: Readonly<DatasetType>;
/**
* The array of series to display.
* Each type of series has its own specificity.
* Please refer to the appropriate docs page to learn more about it.
*/
series?: AllSeriesType<T>[];
series?: readonly AllSeriesType<T>[];
/**
* Color palette used to colorize multiple series.
* @default rainbowSurgePalette
Expand All @@ -30,7 +30,7 @@ export type UseChartSeriesDefaultizedParameters<T extends ChartSeriesType = Char
* Each type of series has its own specificity.
* Please refer to the appropriate docs page to learn more about it.
*/
series: AllSeriesType<T>[];
series: readonly AllSeriesType<T>[];
/**
* Color palette used to colorize multiple series.
* @default rainbowSurgePalette
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function getRange(
return axis.reverse ? [range[1], range[0]] : range;
}

const isDateData = (data?: any[]): data is Date[] => data?.[0] instanceof Date;
const isDateData = (data?: readonly any[]): data is Date[] => data?.[0] instanceof Date;

function createDateFormatter(
axis: AxisConfig<'band' | 'point', any, ChartsAxisProps>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { ChartsAxisProps } from '../../../../models/axis';
import { DatasetType } from '../../../../models/seriesType/config';

export function defaultizeAxis(
inAxis: MakeOptional<AxisConfig<ScaleName, any, ChartsAxisProps>, 'id'>[] | undefined,
dataset: DatasetType | undefined,
inAxis: readonly MakeOptional<AxisConfig<ScaleName, any, ChartsAxisProps>, 'id'>[] | undefined,
dataset: Readonly<DatasetType> | undefined,
axisName: 'x' | 'y',
) {
const DEFAULT_AXIS_KEY = axisName === 'x' ? DEFAULT_X_AXIS_KEY : DEFAULT_Y_AXIS_KEY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { createAxisFilterMapper, createGetAxisFilters } from './createAxisFilter
import { ZoomAxisFilters, ZoomData } from './zoom.types';
import { createZoomLookup } from './createZoomLookup';

export const createZoomMap = (zoom: ZoomData[]) => {
export const createZoomMap = (zoom: readonly ZoomData[]) => {
const zoomItemMap = new Map<AxisId, ZoomData>();
zoom.forEach((zoomItem) => {
zoomItemMap.set(zoomItem.axisId, zoomItem);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ export interface UseChartCartesianAxisParameters {
* If not provided, a default axis config is used.
* An array of [[AxisConfig]] objects.
*/
xAxis?: MakeOptional<AxisConfig<ScaleName, any, ChartsXAxisProps>, 'id'>[];
xAxis?: readonly MakeOptional<AxisConfig<ScaleName, any, ChartsXAxisProps>, 'id'>[];
/**
* The configuration of the y-axes.
* If not provided, a default axis config is used.
* An array of [[AxisConfig]] objects.
*/
yAxis?: MakeOptional<AxisConfig<ScaleName, any, ChartsYAxisProps>, 'id'>[];
yAxis?: readonly MakeOptional<AxisConfig<ScaleName, any, ChartsYAxisProps>, 'id'>[];
/**
* An array of objects that can be used to populate series and axes data using their `dataKey` property.
*/
dataset?: DatasetType;
dataset?: Readonly<DatasetType>;
/**
* The function called for onClick events.
* The second argument contains information about all line/bar elements at the current mouse position.
Expand Down Expand Up @@ -85,7 +85,7 @@ export interface UseChartCartesianAxisState {
*/
zoom?: {
isInteracting: boolean;
zoomData: ZoomData[];
zoomData: readonly ZoomData[];
};
cartesianAxis: {
x: AxisConfig<ScaleName, any, ChartsXAxisProps>[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ function processColorMap(axisConfig: ZAxisConfig) {
};
}

function getZAxisState(zAxis?: MakeOptional<ZAxisConfig, 'id'>[], dataset?: DatasetType) {
function getZAxisState(
zAxis?: readonly MakeOptional<ZAxisConfig, 'id'>[],
dataset?: Readonly<DatasetType>,
) {
if (!zAxis || zAxis.length === 0) {
return { axis: {}, axisIds: [] };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ export interface UseChartZAxisParameters {
/**
* The configuration of the z-axes.
*/
zAxis?: MakeOptional<ZAxisConfig, 'id'>[];
zAxis?: readonly MakeOptional<ZAxisConfig, 'id'>[];
/**
* An array of objects that can be used to populate series and axes data using their `dataKey` property.
*/
dataset?: DatasetType;
dataset?: Readonly<DatasetType>;
}

export type UseChartZAxisDefaultizedParameters = UseChartZAxisParameters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ export type SeriesProcessorResult<TSeriesType extends ChartSeriesType> = {

export type SeriesProcessor<TSeriesType extends ChartSeriesType> = (
params: SeriesProcessorParams<TSeriesType>,
dataset?: DatasetType,
dataset?: Readonly<DatasetType>,
) => SeriesProcessorResult<TSeriesType>;
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ export type AxisConfig<
/**
* The data used by `'band'` and `'point'` scales.
*/
data?: V[];
data?: readonly V[];
/**
* The key used to retrieve `data` from the `dataset` prop.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/colorMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface OrdinalColorConfig<Value = number | Date | string> {
* The value to map.
* If undefined, it will be integers from 0 to the number of colors.
*/
values?: Value[];
values?: readonly Value[];
/**
* The color palette.
* Items equal to `values[k]` will get the color of `colors[k]`.
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/seriesType/bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface BarSeriesType
/**
* Data associated to each bar.
*/
data?: (number | null)[];
data?: readonly (number | null)[];
/**
* The key used to retrieve data from the dataset.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/seriesType/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@ export type ChartItemIdentifier<T extends ChartSeriesType> =
ChartsSeriesConfig[T]['itemIdentifier'];

export type DatasetElementType<T> = {
[key: string]: T;
[key: string]: Readonly<T>;
};
export type DatasetType<T = number | string | Date | null | undefined> = DatasetElementType<T>[];
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/seriesType/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface LineSeriesType
/**
* Data associated to the line.
*/
data?: (number | null)[];
data?: readonly (number | null)[];
/**
* The key used to retrieve data from the dataset.
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/seriesType/scatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface ScatterSeriesType
extends CommonSeriesType<ScatterValueType | null>,
CartesianSeriesType {
type: 'scatter';
data?: ScatterValueType[];
data?: readonly ScatterValueType[];
markerSize?: number;
/**
* The label to display on the tooltip or the legend. It can be a string or a function.
Expand Down
2 changes: 1 addition & 1 deletion packages/x-charts/src/models/z-axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ContinuousColorConfig, OrdinalColorConfig, PiecewiseColorConfig } from

export interface ZAxisConfig<V = any> {
id: string;
data?: V[];
data?: readonly V[];
/**
* The key used to retrieve `data` from the `dataset` prop.
*/
Expand Down