Skip to content

Commit

Permalink
[charts] Prepare ChartContainerPro for future Zoom changes (mui#13532)
Browse files Browse the repository at this point in the history
Signed-off-by: Jose C Quintas Jr <[email protected]>
Co-authored-by: Flavien DELANGLE <[email protected]>
  • Loading branch information
2 people authored and DungTiger committed Jul 23, 2024
1 parent c0e1cc8 commit 54f3034
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 34 deletions.
361 changes: 361 additions & 0 deletions packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,361 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import { ChartContainerProps } from '@mui/x-charts/ChartContainer';
import { ChartsSurface } from '@mui/x-charts/ChartsSurface';
import { HighlightedProvider, ZAxisContextProvider } from '@mui/x-charts/context';
import {
CartesianContextProvider,
ChartsAxesGradients,
ColorProvider,
DrawingProvider,
InteractionProvider,
SeriesContextProvider,
useChartContainerHooks,
} from '@mui/x-charts/internals';
import { useLicenseVerifier } from '@mui/x-license/useLicenseVerifier';
import { getReleaseInfo } from '../internals/utils/releaseInfo';

const releaseInfo = getReleaseInfo();

export interface ChartContainerProProps extends ChartContainerProps {}

const ChartContainerPro = React.forwardRef(function ChartContainer(
props: ChartContainerProProps,
ref,
) {
const {
width,
height,
series,
margin,
xAxis,
yAxis,
zAxis,
colors,
dataset,
sx,
title,
desc,
disableAxisListener,
highlightedItem,
onHighlightChange,
plugins,
children,
} = props;

useLicenseVerifier('x-charts-pro', releaseInfo);

const {
svgRef,
handleRef,
xExtremumGetters,
yExtremumGetters,
seriesFormatters,
colorProcessors,
} = useChartContainerHooks(ref, plugins);

return (
<DrawingProvider width={width} height={height} margin={margin} svgRef={svgRef}>
<ColorProvider colorProcessors={colorProcessors}>
<SeriesContextProvider
series={series}
colors={colors}
dataset={dataset}
seriesFormatters={seriesFormatters}
>
<CartesianContextProvider
xAxis={xAxis}
yAxis={yAxis}
dataset={dataset}
xExtremumGetters={xExtremumGetters}
yExtremumGetters={yExtremumGetters}
>
<ZAxisContextProvider zAxis={zAxis} dataset={dataset}>
<InteractionProvider>
<HighlightedProvider
highlightedItem={highlightedItem}
onHighlightChange={onHighlightChange}
>
<ChartsSurface
width={width}
height={height}
ref={handleRef}
sx={sx}
title={title}
desc={desc}
disableAxisListener={disableAxisListener}
>
<ChartsAxesGradients />
{children}
</ChartsSurface>
</HighlightedProvider>
</InteractionProvider>
</ZAxisContextProvider>
</CartesianContextProvider>
</SeriesContextProvider>
</ColorProvider>
</DrawingProvider>
);
});

ChartContainerPro.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "pnpm proptypes" |
// ----------------------------------------------------------------------
children: PropTypes.node,
className: PropTypes.string,
/**
* Color palette used to colorize multiple series.
* @default blueberryTwilightPalette
*/
colors: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.string), PropTypes.func]),
/**
* An array of objects that can be used to populate series and axes data using their `dataKey` property.
*/
dataset: PropTypes.arrayOf(PropTypes.object),
desc: PropTypes.string,
/**
* If `true`, the charts will not listen to the mouse move event.
* It might break interactive features, but will improve performance.
* @default false
*/
disableAxisListener: PropTypes.bool,
/**
* The height of the chart in px.
*/
height: PropTypes.number.isRequired,
/**
* The item currently highlighted. Turns highlighting into a controlled prop.
*/
highlightedItem: PropTypes.shape({
dataIndex: PropTypes.number,
seriesId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
}),
/**
* The margin between the SVG and the drawing area.
* It's used for leaving some space for extra information such as the x- and y-axis or legend.
* Accepts an object with the optional properties: `top`, `bottom`, `left`, and `right`.
* @default object Depends on the charts type.
*/
margin: PropTypes.shape({
bottom: PropTypes.number,
left: PropTypes.number,
right: PropTypes.number,
top: PropTypes.number,
}),
/**
* The callback fired when the highlighted item changes.
*
* @param {HighlightItemData | null} highlightedItem The newly highlighted item.
*/
onHighlightChange: PropTypes.func,
/**
* An array of plugins defining how to preprocess data.
* If not provided, the container supports line, bar, scatter and pie charts.
*/
plugins: PropTypes.arrayOf(PropTypes.object),
/**
* 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: PropTypes.arrayOf(PropTypes.object).isRequired,
sx: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
PropTypes.func,
PropTypes.object,
]),
title: PropTypes.string,
viewBox: PropTypes.shape({
height: PropTypes.number,
width: PropTypes.number,
x: PropTypes.number,
y: PropTypes.number,
}),
/**
* The width of the chart in px.
*/
width: PropTypes.number.isRequired,
/**
* The configuration of the x-axes.
* If not provided, a default axis config is used.
* An array of [[AxisConfig]] objects.
*/
xAxis: PropTypes.arrayOf(
PropTypes.shape({
axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
classes: PropTypes.object,
colorMap: PropTypes.oneOfType([
PropTypes.shape({
color: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string.isRequired),
PropTypes.func,
]).isRequired,
max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
type: PropTypes.oneOf(['continuous']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
thresholds: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired,
).isRequired,
type: PropTypes.oneOf(['piecewise']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
type: PropTypes.oneOf(['ordinal']).isRequired,
unknownColor: PropTypes.string,
values: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string])
.isRequired,
),
}),
]),
data: PropTypes.array,
dataKey: PropTypes.string,
disableLine: PropTypes.bool,
disableTicks: PropTypes.bool,
fill: PropTypes.string,
hideTooltip: PropTypes.bool,
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
label: PropTypes.string,
labelFontSize: PropTypes.number,
labelStyle: PropTypes.object,
max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
position: PropTypes.oneOf(['bottom', 'top']),
reverse: PropTypes.bool,
scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']),
slotProps: PropTypes.object,
slots: PropTypes.object,
stroke: PropTypes.string,
tickFontSize: PropTypes.number,
tickInterval: PropTypes.oneOfType([
PropTypes.oneOf(['auto']),
PropTypes.array,
PropTypes.func,
]),
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']),
tickLabelStyle: PropTypes.object,
tickMaxStep: PropTypes.number,
tickMinStep: PropTypes.number,
tickNumber: PropTypes.number,
tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']),
tickSize: PropTypes.number,
valueFormatter: PropTypes.func,
}),
),
/**
* The configuration of the y-axes.
* If not provided, a default axis config is used.
* An array of [[AxisConfig]] objects.
*/
yAxis: PropTypes.arrayOf(
PropTypes.shape({
axisId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
classes: PropTypes.object,
colorMap: PropTypes.oneOfType([
PropTypes.shape({
color: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string.isRequired),
PropTypes.func,
]).isRequired,
max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
type: PropTypes.oneOf(['continuous']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
thresholds: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired,
).isRequired,
type: PropTypes.oneOf(['piecewise']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
type: PropTypes.oneOf(['ordinal']).isRequired,
unknownColor: PropTypes.string,
values: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string])
.isRequired,
),
}),
]),
data: PropTypes.array,
dataKey: PropTypes.string,
disableLine: PropTypes.bool,
disableTicks: PropTypes.bool,
fill: PropTypes.string,
hideTooltip: PropTypes.bool,
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
label: PropTypes.string,
labelFontSize: PropTypes.number,
labelStyle: PropTypes.object,
max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
position: PropTypes.oneOf(['left', 'right']),
reverse: PropTypes.bool,
scaleType: PropTypes.oneOf(['band', 'linear', 'log', 'point', 'pow', 'sqrt', 'time', 'utc']),
slotProps: PropTypes.object,
slots: PropTypes.object,
stroke: PropTypes.string,
tickFontSize: PropTypes.number,
tickInterval: PropTypes.oneOfType([
PropTypes.oneOf(['auto']),
PropTypes.array,
PropTypes.func,
]),
tickLabelInterval: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.func]),
tickLabelPlacement: PropTypes.oneOf(['middle', 'tick']),
tickLabelStyle: PropTypes.object,
tickMaxStep: PropTypes.number,
tickMinStep: PropTypes.number,
tickNumber: PropTypes.number,
tickPlacement: PropTypes.oneOf(['end', 'extremities', 'middle', 'start']),
tickSize: PropTypes.number,
valueFormatter: PropTypes.func,
}),
),
/**
* The configuration of the z-axes.
*/
zAxis: PropTypes.arrayOf(
PropTypes.shape({
colorMap: PropTypes.oneOfType([
PropTypes.shape({
color: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.string.isRequired),
PropTypes.func,
]).isRequired,
max: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
min: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]),
type: PropTypes.oneOf(['continuous']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
thresholds: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number]).isRequired,
).isRequired,
type: PropTypes.oneOf(['piecewise']).isRequired,
}),
PropTypes.shape({
colors: PropTypes.arrayOf(PropTypes.string).isRequired,
type: PropTypes.oneOf(['ordinal']).isRequired,
unknownColor: PropTypes.string,
values: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string])
.isRequired,
),
}),
]),
data: PropTypes.array,
dataKey: PropTypes.string,
id: PropTypes.string,
}),
),
} as any;

export { ChartContainerPro };
1 change: 1 addition & 0 deletions packages/x-charts-pro/src/ChartContainerPro/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ChartContainerPro';
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import * as React from 'react';
import { expect } from 'chai';
import { createRenderer, screen, waitFor } from '@mui/internal-test-utils';
import { LicenseInfo } from '@mui/x-license';
import { sharedLicenseStatuses } from '@mui/x-license/useLicenseVerifier/useLicenseVerifier';
import { ResponsiveChartContainerPro } from './ResponsiveChartContainerPro';

describe('<ResponsiveChartContainerPro /> - License', () => {
const { render } = createRenderer();

beforeEach(() => {
Object.keys(sharedLicenseStatuses).forEach((key) => {
delete sharedLicenseStatuses[key];
});
});

it('should render watermark when the license is missing', async () => {
LicenseInfo.setLicenseKey('');

Expand All @@ -15,7 +22,7 @@ describe('<ResponsiveChartContainerPro /> - License', () => {
).toErrorDev(['MUI X: Missing license key.']);

await waitFor(() => {
expect(screen.getByText('MUI X Missing license key')).to.not.equal(null);
expect(screen.findAllByText('MUI X Missing license key')).to.not.equal(null);
});
});
});
Loading

0 comments on commit 54f3034

Please sign in to comment.