import { Box } from '@mui/material' import type { CategorySize } from '../types' import { styles } from '../style' export interface CategoryBarStackedProps { /** One value per series. Zero values render no segment (visually + in the DOM). */ values: readonly number[] /** One color per series. Resolved upstream by `CategoryUI.colorAt`. */ colors: readonly string[] /** * Shared denominator across all rows + series (or `maxOverride`). Same * value `CategoryBar` uses — segments scale identically to single-bar rows * so cross-row comparison is preserved. */ maxValue: number /** Visual density. Forwarded to the track styling; segments inherit height. */ size?: CategorySize } /** * Stacked horizontal bar: one rounded track containing N square segments * placed side-by-side. Each segment's width is `value_i / maxValue * 100%` * and its left offset is the cumulative sum of preceding values. Square * interior edges + the parent track's `overflow: hidden` + rounded radius * mean the outer ends of the stacked bar match a single `CategoryBar` while * interior segment boundaries meet cleanly. * * Pure presentation — selection / dimming is resolved upstream by the row * via the `colors` prop. Each segment carries `data-bar-fill='true'` so the * existing row-hover brightening selector still fires on every segment. */ export function CategoryBarStacked({ values, colors, maxValue, size = 'small', }: CategoryBarStackedProps) { // Cumulative offsets pre-computed up front so the render map function // stays pure (no mutable closure variable — keeps the React Compiler // immutability check happy). const offsets: number[] = [] { let acc = 0 for (const v of values) { offsets.push(acc) acc += v } } return ( {values.map((v, i) => { if (v <= 0) return null const leftPct = maxValue > 0 ? (offsets[i]! / maxValue) * 100 : 0 const pct = maxValue > 0 ? (v / maxValue) * 100 : 0 return ( ) })} ) }