diff --git a/docs/data/charts/export/ExportChartAsImage.tsx b/docs/data/charts/export/ExportChartAsImage.tsx index b1ebea18faf81..e046742331a04 100644 --- a/docs/data/charts/export/ExportChartAsImage.tsx +++ b/docs/data/charts/export/ExportChartAsImage.tsx @@ -73,7 +73,7 @@ function ExportParamsSelector({ } export default function ExportChartAsImage() { - const apiRef = React.useRef(undefined); + const apiRef = React.useRef>(undefined); return ( diff --git a/docs/data/charts/export/ExportCompositionNoSnap.tsx b/docs/data/charts/export/ExportCompositionNoSnap.tsx index 0f0d03c85e464..9a3bc2e79fd4d 100644 --- a/docs/data/charts/export/ExportCompositionNoSnap.tsx +++ b/docs/data/charts/export/ExportCompositionNoSnap.tsx @@ -25,7 +25,7 @@ function CustomChartWrapper({ children }: React.PropsWithChildren) { } export default function ExportCompositionNoSnap() { - const apiRef = React.useRef(undefined); + const apiRef = React.useRef>(undefined); return ( diff --git a/docs/data/charts/export/PrintChart.js b/docs/data/charts/export/PrintChart.js index 9fd8617952a03..2fcb3abbca0f3 100644 --- a/docs/data/charts/export/PrintChart.js +++ b/docs/data/charts/export/PrintChart.js @@ -1,11 +1,19 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; +import Select from '@mui/material/Select'; +import InputLabel from '@mui/material/InputLabel'; +import FormControl from '@mui/material/FormControl'; +import MenuItem from '@mui/material/MenuItem'; import { ScatterChartPro } from '@mui/x-charts-pro/ScatterChartPro'; +import { BarChartPro } from '@mui/x-charts-pro/BarChartPro'; +import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; +import { Heatmap } from '@mui/x-charts-pro/Heatmap'; import { data } from './randomData'; +import { heatmapData } from './heatmapData'; -const series = [ +const scatterSeries = [ { label: 'Series A', data: data.map((v) => ({ x: v.x1, y: v.y1, id: v.id })), @@ -16,19 +24,90 @@ const series = [ }, ]; +const series = [ + { label: 'Series A', data: data.map((p) => p.y1) }, + { label: 'Series B', data: data.map((p) => p.y2) }, +]; + export default function PrintChart() { + const [chartType, setChartType] = React.useState('scatter'); const apiRef = React.useRef(undefined); + const handleChange = (event) => setChartType(event.target.value); + return ( - - + + Chart Type + + + + + ); } + +function Chart({ apiRef, type }) { + switch (type) { + case 'scatter': + return ; + + case 'line': + return ( + p.x1).toSorted((a, b) => a - b) }]} + series={series} + /> + ); + + case 'bar': + return ( + Math.round(p.x1)).toSorted((a, b) => a - b) }, + ]} + series={series} + /> + ); + + case 'heatmap': + return ( + + ); + + default: + throw new Error(`Unknown chart type: ${type}`); + } +} diff --git a/docs/data/charts/export/PrintChart.tsx b/docs/data/charts/export/PrintChart.tsx index aa7b6d8a20d9c..76215e6368d68 100644 --- a/docs/data/charts/export/PrintChart.tsx +++ b/docs/data/charts/export/PrintChart.tsx @@ -1,11 +1,19 @@ import * as React from 'react'; import Stack from '@mui/material/Stack'; import Button from '@mui/material/Button'; +import Select, { SelectChangeEvent } from '@mui/material/Select'; +import InputLabel from '@mui/material/InputLabel'; +import FormControl from '@mui/material/FormControl'; +import MenuItem from '@mui/material/MenuItem'; import { ScatterChartPro } from '@mui/x-charts-pro/ScatterChartPro'; import { ChartProApi } from '@mui/x-charts-pro/ChartContainerPro'; +import { BarChartPro } from '@mui/x-charts-pro/BarChartPro'; +import { LineChartPro } from '@mui/x-charts-pro/LineChartPro'; +import { Heatmap } from '@mui/x-charts-pro/Heatmap'; import { data } from './randomData'; +import { heatmapData } from './heatmapData'; -const series = [ +const scatterSeries = [ { label: 'Series A', data: data.map((v) => ({ x: v.x1, y: v.y1, id: v.id })), @@ -15,20 +23,101 @@ const series = [ data: data.map((v) => ({ x: v.x1, y: v.y2, id: v.id })), }, ]; +const series = [ + { label: 'Series A', data: data.map((p) => p.y1) }, + { label: 'Series B', data: data.map((p) => p.y2) }, +]; + +type ChartType = 'scatter' | 'line' | 'bar' | 'heatmap'; export default function PrintChart() { + const [chartType, setChartType] = React.useState('scatter'); const apiRef = React.useRef(undefined); + const handleChange = (event: SelectChangeEvent) => + setChartType(event.target.value as ChartType); + return ( - - + + Chart Type + + + + + ); } + +function Chart({ + apiRef, + type, +}: { + apiRef: React.RefObject | undefined>; + type: T; +}) { + switch (type) { + case 'scatter': + return ( + | undefined>} + height={300} + series={scatterSeries} + /> + ); + case 'line': + return ( + | undefined>} + height={300} + xAxis={[{ data: data.map((p) => p.x1).toSorted((a, b) => a - b) }]} + series={series} + /> + ); + case 'bar': + return ( + | undefined>} + height={300} + xAxis={[ + { data: data.map((p) => Math.round(p.x1)).toSorted((a, b) => a - b) }, + ]} + series={series} + /> + ); + case 'heatmap': + return ( + | undefined>} + xAxis={[{ data: [1, 2, 3, 4] }]} + yAxis={[{ data: ['A', 'B', 'C', 'D', 'E'] }]} + series={[{ data: heatmapData }]} + height={300} + hideLegend={false} + /> + ); + default: + throw new Error(`Unknown chart type: ${type}`); + } +} diff --git a/docs/data/charts/export/PrintChart.tsx.preview b/docs/data/charts/export/PrintChart.tsx.preview deleted file mode 100644 index 4014a2409237b..0000000000000 --- a/docs/data/charts/export/PrintChart.tsx.preview +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/docs/data/charts/export/export.md b/docs/data/charts/export/export.md index 5c558584b03e6..ad0056d0cd474 100644 --- a/docs/data/charts/export/export.md +++ b/docs/data/charts/export/export.md @@ -8,7 +8,7 @@ components: ScatterChartPro, BarChartPro, LineChartPro

Charts can be printed and exported as PDF.

-Export is available on the Pro version of the charts: ``, ``, ``. +Export is available for the following charts: ``, ``, ``, ``. ## Print/Export as PDF diff --git a/docs/data/charts/export/heatmapData.js b/docs/data/charts/export/heatmapData.js new file mode 100644 index 0000000000000..b27cfaf6cbe16 --- /dev/null +++ b/docs/data/charts/export/heatmapData.js @@ -0,0 +1,22 @@ +export const heatmapData = [ + [0, 0, 10], + [0, 1, 20], + [0, 2, 40], + [0, 3, 90], + [0, 4, 70], + [1, 0, 30], + [1, 1, 50], + [1, 2, 10], + [1, 3, 70], + [1, 4, 40], + [2, 0, 50], + [2, 1, 20], + [2, 2, 90], + [2, 3, 20], + [2, 4, 70], + [3, 0, 40], + [3, 1, 50], + [3, 2, 20], + [3, 3, 70], + [3, 4, 90], +]; diff --git a/docs/data/charts/export/heatmapData.ts b/docs/data/charts/export/heatmapData.ts new file mode 100644 index 0000000000000..b88d55c474ec4 --- /dev/null +++ b/docs/data/charts/export/heatmapData.ts @@ -0,0 +1,24 @@ +import { HeatmapValueType } from '@mui/x-charts-pro/models'; + +export const heatmapData: HeatmapValueType[] = [ + [0, 0, 10], + [0, 1, 20], + [0, 2, 40], + [0, 3, 90], + [0, 4, 70], + [1, 0, 30], + [1, 1, 50], + [1, 2, 10], + [1, 3, 70], + [1, 4, 40], + [2, 0, 50], + [2, 1, 20], + [2, 2, 90], + [2, 3, 20], + [2, 4, 70], + [3, 0, 40], + [3, 1, 50], + [3, 2, 20], + [3, 3, 70], + [3, 4, 90], +]; diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx index 91a742fc91587..41fe63f46c9ba 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartContainerPro.tsx @@ -19,8 +19,6 @@ type ChartContainerProComponent = < props: ChartContainerProProps & { ref?: React.ForwardedRef }, ) => React.JSX.Element; -export type ChartProApi = NonNullable['current']>; - /** * It sets up the data providers as well as the `` for the chart. * diff --git a/packages/x-charts-pro/src/ChartContainerPro/ChartProApi.ts b/packages/x-charts-pro/src/ChartContainerPro/ChartProApi.ts new file mode 100644 index 0000000000000..cc73c9261df7c --- /dev/null +++ b/packages/x-charts-pro/src/ChartContainerPro/ChartProApi.ts @@ -0,0 +1,28 @@ +import { ChartAnyPluginSignature, ChartPublicAPI } from '@mui/x-charts/internals'; +import { HeatmapPluginsSignatures } from '../Heatmap/Heatmap.plugins'; +import { LineChartProPluginsSignatures } from '../LineChartPro/LineChartPro.plugins'; +import { ScatterChartProPluginsSignatures } from '../ScatterChartPro/ScatterChartPro.plugins'; +import { BarChartProPluginsSignatures } from '../BarChartPro/BarChartPro.plugins'; +import { AllPluginSignatures, DefaultPluginSignatures } from '../internals/plugins/allPlugins'; + +type PluginsPerSeriesType = { + heatmap: HeatmapPluginsSignatures; + line: LineChartProPluginsSignatures; + scatter: ScatterChartProPluginsSignatures; + bar: BarChartProPluginsSignatures; + /* Special value when creating a chart using composition. */ + composition: DefaultPluginSignatures; +}; + +/** + * The API of the chart `apiRef` object. + * The chart type can be passed as the first generic parameter to narrow down the API to the specific chart type. + * @example ChartProApi<'bar'> + */ +export type ChartProApi< + TSeries extends keyof PluginsPerSeriesType | undefined = undefined, + TSignatures extends + readonly ChartAnyPluginSignature[] = TSeries extends keyof PluginsPerSeriesType + ? PluginsPerSeriesType[TSeries] + : AllPluginSignatures, +> = ChartPublicAPI; diff --git a/packages/x-charts-pro/src/ChartContainerPro/index.ts b/packages/x-charts-pro/src/ChartContainerPro/index.ts index fc6cf1b3c5168..5e89057b0e215 100644 --- a/packages/x-charts-pro/src/ChartContainerPro/index.ts +++ b/packages/x-charts-pro/src/ChartContainerPro/index.ts @@ -1,3 +1,4 @@ import '../typeOverloads'; export * from './ChartContainerPro'; +export * from './ChartProApi'; diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.plugins.ts b/packages/x-charts-pro/src/Heatmap/Heatmap.plugins.ts index c8e6d8551ca2c..38ec10bc4c354 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.plugins.ts +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.plugins.ts @@ -9,12 +9,17 @@ import { UseChartHighlightSignature, ConvertSignaturesIntoPlugins, } from '@mui/x-charts/internals'; +import { + useChartProExport, + UseChartProExportSignature, +} from '../internals/plugins/useChartProExport'; export type HeatmapPluginsSignatures = [ UseChartZAxisSignature, UseChartCartesianAxisSignature<'heatmap'>, UseChartInteractionSignature, UseChartHighlightSignature, + UseChartProExportSignature, ]; export const HEATMAP_PLUGINS = [ @@ -22,4 +27,5 @@ export const HEATMAP_PLUGINS = [ useChartCartesianAxis, useChartInteraction, useChartHighlight, + useChartProExport, ] as ConvertSignaturesIntoPlugins; diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index e6ff321518d49..bbbfffef85121 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -140,6 +140,7 @@ const Heatmap = React.forwardRef(function Heatmap( ) { const props = useThemeProps({ props: inProps, name: 'MuiHeatmap' }); const { + apiRef, xAxis, yAxis, zAxis, @@ -209,6 +210,7 @@ const Heatmap = React.forwardRef(function Heatmap( return ( + apiRef={apiRef} seriesConfig={seriesConfig} series={series.map((s) => ({ type: 'heatmap', @@ -257,7 +259,10 @@ Heatmap.propTypes = { // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- apiRef: PropTypes.shape({ - current: PropTypes.object, + current: PropTypes.shape({ + exportAsImage: PropTypes.func.isRequired, + exportAsPrint: PropTypes.func.isRequired, + }), }), className: PropTypes.string, /**