import type { KeyboardEvent } from 'react' import { Box, Typography } from '@mui/material' import { CategoryBarStacked } from './category-bar-stacked' import type { CategoryKey, CategorySize } from '../types' import { styles } from '../style' export interface CategoryRowStackedProps { /** Raw category key — what gets emitted to `onToggle`. */ name: CategoryKey /** Display label (post-`labelFormatter`). Falls back to `name`. */ displayName?: string | number /** One value per series. Zero values still appear in the breakdown row. */ values: readonly number[] /** One color per series (palette + per-series overrides resolved upstream). */ colors: readonly string[] /** Series names for the breakdown row. Missing entries fall back to `Series N`. */ seriesNames: readonly string[] formatter: (n: number) => string selected: boolean onToggle: (name: CategoryKey) => void /** Bar visual density. Forwarded to the inner {@link CategoryBarStacked}. */ size?: CategorySize } /** * Stacked-mode category row: label + total share a header line; a single * segmented bar sits below; an inline breakdown lists each series with its * formatted value. Click anywhere in the row toggles selection by `name`. * * Per-row normalization: the stacked bar always fills 100% of the track, * with each segment sized as `value_i / sum(values)`. This is intentionally * different from `CategoryRowMulti` (which scales bars against the global * `maxValue` for cross-row comparison) — in stacked mode the comparable * axis is the proportion of each series within the row, not the row's * total relative to other rows. The total numeric value is still shown in * the header so the per-row magnitude isn't lost. * * Visual selection / dim signal lives entirely in the segment colors * (`colors` prop) — every series in a dimmed row receives * `theme.palette.action.disabled`. The bar visually collapses to a single * grey shape when dimmed, but the breakdown text stays at full color so the * per-series values remain legible. */ export function CategoryRowStacked({ name, displayName, values, colors, seriesNames, formatter, selected, onToggle, size, }: CategoryRowStackedProps) { const handleKey = (e: KeyboardEvent): void => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() onToggle(name) } } const total = values.reduce((a, b) => a + b, 0) return ( onToggle(name)} onKeyDown={handleKey} sx={styles.rowStacked} > {displayName ?? name} {formatter(total)} {values.map((v, i) => ( // Series name is the stable identity for the breakdown line. {`${seriesNames[i] ?? `Series ${i + 1}`}: ${formatter(v)}`} ))} ) }