import type { ScaleLinear, ScaleTime } from 'd3-scale'; import { isNil } from 'ramda'; import type { MutableRefObject } from 'react'; import { Axis, AxisYRight } from '../../../common/Axes/models'; import { getDates, getTimeSeriesForLines, getYScale } from '../../../common/timeSeries'; import type { Line, TimeValue } from '../../../common/timeSeries/models'; import { getPointRadius, getStyle } from '../../../common/utils'; import { displayArea } from '../../helpers/index'; import GuidingLines from '../../InteractiveComponents/AnchorPoint/GuidingLines'; import RegularAnchorPoint, { getYAnchorPoint } from '../../InteractiveComponents/AnchorPoint/RegularAnchorPoint'; import type { DisplayAnchor, GlobalAreaLines, LineStyle } from '../../models'; import Point from './Point'; import RegularLine from './RegularLines'; import useRegularLines from './RegularLines/useRegularLines'; import StackedLines from './StackedLines'; import useStackedLines from './StackedLines/useStackedLines'; import WrapperThresholdLines from './Threshold'; import { canDisplayThreshold, requiredNumberLinesThreshold } from './Threshold/models'; interface Props extends GlobalAreaLines { displayAnchor?: DisplayAnchor; displayedLines: Array; graphSvgRef: MutableRefObject; height: number; scale?: 'linear' | 'logarithmic'; scaleLogarithmicBase?: number; timeSeries: Array; width: number; xScale: ScaleTime; yScalesPerUnit: Record>; lineStyle: LineStyle | Array; hasSecondUnit?: boolean; maxLeftAxisCharacters: number; firstUnit?: string; secondUnit?: string; axis?: { axisYLeft?: Axis; axisYRight?: AxisYRight; }; } const Lines = ({ height, graphSvgRef, width, displayAnchor, yScalesPerUnit, xScale, timeSeries, displayedLines, areaThresholdLines, areaStackedLines, areaRegularLines, scale, scaleLogarithmicBase, lineStyle, hasSecondUnit, maxLeftAxisCharacters, firstUnit, secondUnit, axis }: Props): JSX.Element => { const { stackedLinesData, invertedStackedLinesData } = useStackedLines({ lines: displayedLines, timeSeries }); const { regularLines } = useRegularLines({ lines: displayedLines }); const displayThresholdArea = displayedLines?.length >= requiredNumberLinesThreshold && canDisplayThreshold(areaThresholdLines); const displayAreaRegularLines = (areaRegularLines?.display ?? true) && displayArea(regularLines); const displayGuidingLines = displayAnchor?.displayGuidingLines ?? true; const commonStackedLinesProps = { displayAnchor: displayGuidingLines, graphHeight: height, graphSvgRef, graphWidth: width, hasSecondUnit, maxLeftAxisCharacters, xScale }; // @ts-expect-error - suppressing pre-existing type mismatch const leftScale = yScalesPerUnit[axis?.axisYLeft?.unit ?? firstUnit]; // @ts-expect-error - suppressing pre-existing type mismatch const rightScale = yScalesPerUnit[axis?.axisYRight?.unit ?? secondUnit]; const hasUnitDisplayed = Boolean(firstUnit || secondUnit) || Boolean( axis?.axisYLeft?.unit || axis?.axisYLeft?.displayUnit || (axis?.axisYRight?.unit && axis?.axisYRight?.displayUnit) ); return ( {displayGuidingLines && ( )} {(areaStackedLines?.display ?? true) && ( <> {Object.entries(stackedLinesData).map( ([stackedKey, { lines, timeSeries: stackedTimeSeries }]) => { const [, unit] = stackedKey.split('-'); const yScale = unit === '' && yScalesPerUnit[unit] === undefined ? // @ts-expect-error - suppressing pre-existing type mismatch yScalesPerUnit[undefined] : yScalesPerUnit[unit]; return ( // @ts-expect-error - suppressing pre-existing type mismatch ); } )} {Object.entries(invertedStackedLinesData).map( ([stackedKey, { lines, timeSeries: stackedTimeSeries }]) => { const [, unit] = stackedKey.split('-'); return ( // @ts-expect-error - suppressing pre-existing type mismatch ); } )} )} {displayThresholdArea && ( )} {displayAreaRegularLines ? regularLines.map( ({ areaColor, transparency, lineColor, filled, unit, highlight, invert, metric_id, ...rest }) => { const yScale = getYScale({ invert, scale, scaleLogarithmicBase, unit, yScalesPerUnit }); const relatedTimeSeries = getTimeSeriesForLines({ invert, lines: [ { areaColor, filled, highlight, invert, lineColor, metric_id, transparency, unit, ...rest } ], timeSeries }); const style = getStyle({ metricId: metric_id, // @ts-expect-error - suppressing pre-existing type mismatch style: lineStyle }) as LineStyle; return ( {displayGuidingLines && ( )} {style?.showPoints && getDates(relatedTimeSeries).map((timeTick) => ( ))} ); } ) : null} ); }; export default Lines;