// StackedSegment.tsx // This component renders a stack of column segments for a single x-axis category in a grouped/stacked column chart. // Each segment represents a value from a different series, stacked vertically. Uses the Segment component for rendering each bar. import React, { memo } from 'react'; import { deepCompareValue } from '../../../utils/helpers'; import useScaleLinearY from '../shared/hooks/useScaleLinearY'; import type { DataValue, YAxisConfig } from '../types'; import Segment from './Segment'; interface StackedSegmentProps { stackedData: Array; seriesLabels: Array; xLabel: string; yAxisConfig: YAxisConfig; coordinates: { yStart: number; yEnd: number; xStart: number; xEnd: number }; xCenter: number; xIndex: number; /** * Called when a bar (column segment) is pressed. */ onBarPress?: (info: { value: number | undefined; xLabel: string; seriesLabel: string; seriesIndex: number; xIndex: number; }) => void; /** * A function that maps series labels to colors. */ colorScale?: (label: string) => string | undefined; } /** * Renders a stack of column segments for a single x-axis category. * Each segment corresponds to a value in stackedData and is colored by series. * Skips undefined values. Used for grouped/stacked column charts. */ const StackedSegment: React.FC = ({ stackedData, seriesLabels, xLabel, yAxisConfig, coordinates, xCenter, xIndex, onBarPress, colorScale, }) => { const { yStart, yEnd } = coordinates; const stackedMaxY = yAxisConfig.maxValue ?? 0; const scaleY = useScaleLinearY({ maxValue: stackedMaxY, minValue: 0, yStart, yEnd, }); let yStack = 0; // running sum for stacking return stackedData.map((value, index) => { // If value is undefined, skip this segment if (value === undefined) { return null; } const prevYStack = yStack; yStack += value ?? 0; // y0 is the bottom of the stack, y1 is the top const y0 = scaleY(prevYStack); const y1 = scaleY(yStack); const colHeight = y0 - y1; // since y increases downward in SVG const seriesLabel = seriesLabels[index]; return ( onBarPress({ value, xLabel, seriesLabel, seriesIndex: index, xIndex, }) : undefined } /> ); }); }; export default memo(StackedSegment, deepCompareValue);