|
|
|
import { Box, linearProgressClasses, styled } from '@mui/material';
|
|
|
|
import { FC, ReactElement, createElement, useMemo } from 'react';
|
|
|
|
|
|
|
|
import { GREY } from '../../lib/consts/DEFAULT_THEME';
|
|
|
|
|
|
|
|
import RoundedLinearProgress from './BorderLinearProgress';
|
|
|
|
import Underline from './Underline';
|
|
|
|
|
|
|
|
const ThinRoundedLinearProgress = styled(RoundedLinearProgress)({
|
|
|
|
height: '.4em',
|
|
|
|
});
|
|
|
|
|
|
|
|
const ThinUnderline = styled(Underline)({
|
|
|
|
height: '.2em',
|
|
|
|
});
|
|
|
|
|
|
|
|
const StackBar: FC<StackBarProps> = (props) => {
|
|
|
|
const { barProps = {}, thin, underlineProps, value } = props;
|
|
|
|
|
|
|
|
const { sx: barSx, ...restBarProps } = barProps;
|
|
|
|
|
|
|
|
const values = useMemo<Record<string, StackBarValue>>(
|
|
|
|
() => ('value' in value ? { default: value as StackBarValue } : value),
|
|
|
|
[value],
|
|
|
|
);
|
|
|
|
|
|
|
|
const entries = useMemo<[string, StackBarValue][]>(
|
|
|
|
() => Object.entries(values).reverse(),
|
|
|
|
[values],
|
|
|
|
);
|
|
|
|
|
|
|
|
const creatableBar = useMemo(
|
|
|
|
() => (thin ? ThinRoundedLinearProgress : RoundedLinearProgress),
|
|
|
|
[thin],
|
|
|
|
);
|
|
|
|
|
|
|
|
const creatableUnderline = useMemo(
|
|
|
|
() => (thin ? ThinUnderline : Underline),
|
|
|
|
[thin],
|
|
|
|
);
|
|
|
|
|
|
|
|
const bars = useMemo<ReactElement[]>(
|
|
|
|
() =>
|
|
|
|
entries.map<ReactElement>(
|
|
|
|
([id, { colour = GREY, value: val }], index) => {
|
|
|
|
const backgroundColor =
|
|
|
|
typeof colour === 'string'
|
|
|
|
? colour
|
|
|
|
: Object.entries(colour).findLast(
|
|
|
|
([mark]) => val >= Number(mark),
|
|
|
|
)?.[1] ?? GREY;
|
|
|
|
|
|
|
|
let position: 'absolute' | 'relative' = 'relative';
|
|
|
|
let top: 0 | undefined;
|
|
|
|
let width: string | undefined;
|
|
|
|
|
|
|
|
if (index) {
|
|
|
|
position = 'absolute';
|
|
|
|
top = 0;
|
|
|
|
width = '100%';
|
|
|
|
}
|
|
|
|
|
|
|
|
return createElement(creatableBar, {
|
|
|
|
key: `stack-bar-${id}`,
|
|
|
|
sx: {
|
|
|
|
position,
|
|
|
|
top,
|
|
|
|
width,
|
|
|
|
|
|
|
|
[`& .${linearProgressClasses.bar}`]: {
|
|
|
|
backgroundColor,
|
|
|
|
},
|
|
|
|
|
|
|
|
...barSx,
|
|
|
|
},
|
|
|
|
variant: 'determinate',
|
|
|
|
value: val,
|
|
|
|
...restBarProps,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
),
|
|
|
|
[barSx, entries, creatableBar, restBarProps],
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Box position="relative">
|
|
|
|
{bars}
|
|
|
|
{createElement(creatableUnderline, underlineProps)}
|
|
|
|
</Box>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default StackBar;
|