diff --git a/docs/data/charts/line-demo/LineWithPrediction.js b/docs/data/charts/line-demo/LineWithPrediction.js new file mode 100644 index 000000000000..277ce031aeb0 --- /dev/null +++ b/docs/data/charts/line-demo/LineWithPrediction.js @@ -0,0 +1,70 @@ +import * as React from 'react'; +import { LineChart, AnimatedLine } from '@mui/x-charts/LineChart'; +import { useChartId, useDrawingArea, useXScale } from '@mui/x-charts/hooks'; + +function CustomAnimatedLine(props) { + const { limit, sxBefore, sxAfter, ...other } = props; + const { top, bottom, height, left, width } = useDrawingArea(); + const scale = useXScale(); + const chartId = useChartId(); + + if (limit === undefined) { + return ; + } + + const limitPosition = scale(limit); // Convert value to x coordinate. + + if (limitPosition === undefined) { + return ; + } + + const clipIdleft = `${chartId}-${props.ownerState.id}-line-limit-${limit}-1`; + const clipIdRight = `${chartId}-${props.ownerState.id}-line-limit-${limit}-2`; + return ( + + {/* Clip to show the line before the limit */} + + + + {/* Clip to show the line after the limit */} + + + + + + + + + + + ); +} + +export default function LineWithPrediction() { + return ( + `${v}${i.dataIndex > 5 ? ' (estimated)' : ''}`, + }, + ]} + xAxis={[{ data: [0, 1, 2, 3, 4, 5, 6, 7, 8] }]} + height={200} + width={400} + slots={{ line: CustomAnimatedLine }} + slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } }} + /> + ); +} diff --git a/docs/data/charts/line-demo/LineWithPrediction.tsx b/docs/data/charts/line-demo/LineWithPrediction.tsx new file mode 100644 index 000000000000..55fd42deb244 --- /dev/null +++ b/docs/data/charts/line-demo/LineWithPrediction.tsx @@ -0,0 +1,77 @@ +import * as React from 'react'; +import { LineChart, AnimatedLine, AnimatedLineProps } from '@mui/x-charts/LineChart'; +import { useChartId, useDrawingArea, useXScale } from '@mui/x-charts/hooks'; +import { SxProps, Theme } from '@mui/system'; + +interface CustomAnimatedLineProps extends AnimatedLineProps { + limit?: number; + sxBefore?: SxProps; + sxAfter?: SxProps; +} + +function CustomAnimatedLine(props: CustomAnimatedLineProps) { + const { limit, sxBefore, sxAfter, ...other } = props; + const { top, bottom, height, left, width } = useDrawingArea(); + const scale = useXScale(); + const chartId = useChartId(); + + if (limit === undefined) { + return ; + } + + const limitPosition = scale(limit); // Convert value to x coordinate. + + if (limitPosition === undefined) { + return ; + } + + const clipIdleft = `${chartId}-${props.ownerState.id}-line-limit-${limit}-1`; + const clipIdRight = `${chartId}-${props.ownerState.id}-line-limit-${limit}-2`; + return ( + + {/* Clip to show the line before the limit */} + + + + {/* Clip to show the line after the limit */} + + + + + + + + + + + ); +} + +export default function LineWithPrediction() { + return ( + `${v}${i.dataIndex > 5 ? ' (estimated)' : ''}`, + }, + ]} + xAxis={[{ data: [0, 1, 2, 3, 4, 5, 6, 7, 8] }]} + height={200} + width={400} + slots={{ line: CustomAnimatedLine }} + slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } as any }} + /> + ); +} diff --git a/docs/data/charts/line-demo/LineWithPrediction.tsx.preview b/docs/data/charts/line-demo/LineWithPrediction.tsx.preview new file mode 100644 index 000000000000..1dc0a8f94a59 --- /dev/null +++ b/docs/data/charts/line-demo/LineWithPrediction.tsx.preview @@ -0,0 +1,14 @@ + `${v}${i.dataIndex > 5 ? ' (estimated)' : ''}`, + }, + ]} + xAxis={[{ data: [0, 1, 2, 3, 4, 5, 6, 7, 8] }]} + height={200} + width={400} + slots={{ line: CustomAnimatedLine }} + slotProps={{ line: { limit: 5, sxAfter: { strokeDasharray: '10 5' } } as any }} +/> \ No newline at end of file diff --git a/docs/data/charts/line-demo/line-demo.md b/docs/data/charts/line-demo/line-demo.md index d79eae58f84a..e74ae9c5cade 100644 --- a/docs/data/charts/line-demo/line-demo.md +++ b/docs/data/charts/line-demo/line-demo.md @@ -31,3 +31,15 @@ components: LineChart, LineElement, LineHighlightElement, LineHighlightPlot, Lin ## LineChartConnectNulls {{"demo": "LineChartConnectNulls.js"}} + +## Line with forecast + +To show that parts of the data have different meanings, you can render stylised lines for each of them. + +In the following example, the chart shows a dotted line to exemplify that the data is estimated. +To do so, the `slots.line` is set with a custom components that render the default line twice. + +- The first one is clipped to show known values (from the left of the chart to the limit). +- The second one is clipped to show predictions (from the limit to the right of the chart) with dash styling. + +{{"demo": "LineWithPrediction.js"}}