import { Shape } from '@visx/visx'; import type { ScaleLinear, ScaleTime } from 'd3-scale'; import { all, equals, isNil, map, not, nth, path, pipe, prop, type } from 'ramda'; import type { ReactElement } from 'react'; import { getDates, getTime } from '../../../../common/timeSeries'; import type { Line, TimeValue } from '../../../../common/timeSeries/models'; import { getPointRadius, getStrokeDashArray, getStyle } from '../../../../common/utils'; import { getCurveFactory, getFillColor } from '../../../common'; import type { StackValue } from '../../../InteractiveComponents/AnchorPoint/models'; import StackedAnchorPoint, { getYAnchorPoint } from '../../../InteractiveComponents/AnchorPoint/StackedAnchorPoint'; import type { LineStyle } from '../../../models'; import Point from '../Point'; interface Props { areaTransparency?: number; curve: 'linear' | 'step' | 'natural'; dashLength?: number; dashOffset?: number; displayAnchor: boolean; dotOffset?: number; lineWidth?: number; lines: Array; showArea?: boolean; showPoints?: boolean; timeSeries: Array; xScale: ScaleTime; yScale: ScaleLinear; lineStyle: LineStyle | Array; hasSecondUnit?: boolean; maxLeftAxisCharacters: number; } const StackLines = ({ timeSeries, lines, yScale, xScale, displayAnchor, lineStyle, hasSecondUnit, maxLeftAxisCharacters }: Props): ReactElement => { const curveType = getCurveFactory( (equals(type(lineStyle), 'Array') ? (lineStyle as Array)?.[0].curve : (lineStyle as LineStyle)?.curve) || 'linear' ); return ( { return pipe( // @ts-expect-error - suppressing pre-existing type mismatch map(prop('metric_id')) as unknown as ( displayedLines: Array ) => Array, all((metric_id) => pipe(path(['data', metric_id]), isNil, not)(d)) )(lines); }} keys={map(prop('metric_id'), lines)} x={(d): number => xScale(getTime(d.data)) ?? 0} y0={(d): number => yScale(d[0]) ?? 0} y1={(d): number => yScale(d[1]) ?? 0} > {({ stacks, path: linePath }): Array => { return stacks.map((stack, index) => { const { areaColor, transparency, lineColor, highlight, metric_id } = nth(index, lines) as Line; const style = getStyle({ metricId: metric_id, // @ts-expect-error - suppressing pre-existing type mismatch style: lineStyle }) as LineStyle; const formattedLineWidth = style?.lineWidth ?? 2; const formattedTransparency = isNil(style?.areaTransparency) ? transparency || 80 : style.areaTransparency; const linePartStack = stack.map((stackValue, index) => { if (isNil(timeSeries[index][metric_id])) { return [stackValue[0], null]; } return stackValue; }); return ( {displayAnchor && ( } timeSeries={timeSeries} transparency={transparency} xScale={xScale} yScale={yScale} /> )} {style?.showPoints && getDates(timeSeries).map((timeTick) => ( , timeTick, yScale })} yScale={yScale} /> ))} { return !isNil(d[1]); }} fill="none" opacity={highlight === false ? 0.3 : 1} stroke={lineColor} strokeDasharray={getStrokeDashArray({ dashLength: style?.dashLength, dashOffset: style?.dashOffset, dotOffset: style?.dotOffset, lineWidth: style?.lineWidth ?? 2 })} strokeWidth={ highlight ? Math.ceil(formattedLineWidth * 1.3) : formattedLineWidth } // @ts-expect-error - suppressing pre-existing type mismatch x={(d) => xScale(getTime(d.data)) ?? 0} y={(d) => yScale(d[1] ?? 0) ?? 0} /> ); }); }} ); }; export default StackLines;