monday-ui-react-core
Version:
Official monday.com UI resources for application development in React.js
181 lines (169 loc) • 4.87 kB
JSX
import React, { useMemo, forwardRef } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import { baseClassName, PROGRESS_BAR_STYLES } from "./LinearProgressBarConstants";
import { calculatePercentage } from "./LinearProgressBarHelpers";
import Bar from "./Bar/Bar";
import PercentageLabel from "../PercentageLabel/PercentageLabel";
import { SIZES } from "../../../constants/sizes";
import "./LinearProgressBar.scss";
const LinearProgressBar = forwardRef(
(
{
min,
max,
value,
valueSecondary,
animated,
barStyle,
className,
size,
indicateProgress,
multi,
multiValues,
ariaLabel
},
ref
) => {
const wrapperClassName = useMemo(() => {
const base = `${baseClassName}--wrapper`;
return cx(base, { [`${base}__${size}`]: size }, className);
}, [size, className]);
const valuePercentage = useMemo(() => {
if (multi) {
const firstValue = multiValues && multiValues.length && multiValues[0].value;
if (firstValue === null || firstValue === undefined) return 0;
return calculatePercentage(firstValue, min, max);
}
if (value === null || value === undefined) return 0;
return calculatePercentage(value, min, max);
}, [value, min, max, multi, multiValues]);
const renderMultiBars = useMemo(() => {
if (!multi) return null;
return (
<>
{[...multiValues].reverse().map(({ value: baseValue, color }, i) => (
<Bar
barStyle="none"
value={baseValue}
animated={animated}
baseClass={baseClassName}
color={color}
min={min}
max={max}
/* eslint-disable-next-line react/no-array-index-key */
key={`${baseClassName}_${color}_${i}`}
/>
))}
</>
);
}, [min, max, animated, multiValues, multi]);
const renderPercentage = indicateProgress ? (
<PercentageLabel forElement="linear-progress-bar" className={`${baseClassName}__label`} value={valuePercentage} />
) : null;
const renderBaseBars = !multi ? (
<>
<Bar
barLabelName={ariaLabel}
barStyle={barStyle}
id="linear-progress-bar"
value={valueSecondary}
animated={animated}
baseClass={`${baseClassName}__secondary`}
min={min}
max={max}
/>
<Bar barStyle={barStyle} value={value} animated={animated} baseClass={baseClassName} min={min} max={max} />
</>
) : null;
return (
<div className={wrapperClassName} ref={ref}>
<div className={`${baseClassName}__container`}>
{renderBaseBars}
{renderMultiBars}
</div>
{renderPercentage}
</div>
);
}
);
LinearProgressBar.styles = PROGRESS_BAR_STYLES;
LinearProgressBar.sizes = SIZES;
LinearProgressBar.propTypes = {
/**
* Determine the progress bar style (Supported options exposed through `LinearProgressBar.styles`).
*/
barStyle: PropTypes.oneOf(Object.values(PROGRESS_BAR_STYLES)),
/**
* The progress bar starting value.
*/
min: PropTypes.number,
/**
* The progress bar ending value.
*/
max: PropTypes.number,
/**
* The progress bar current value.
*/
value: PropTypes.number,
/**
* The progress bar secondary value.
*/
valueSecondary: PropTypes.number,
/**
* If set to *true*, animations are used.
*/
animated: PropTypes.bool,
/**
* Set external styling to the progress bar.
*/
className: PropTypes.string,
/**
* Determine the progress bar height (Supported options exposed through `LinearProgressBar.sizes`)
*/
size: PropTypes.oneOf(Object.values(SIZES)),
/**
* Show progress bar progression in percentages
*/
indicateProgress: PropTypes.bool,
/**
* Use multiple bars.
* ***Note:*** `value`, `valueSecondary` & `barStyle` won't be used
*/
multi: PropTypes.bool,
/**
* Array of bar value objects {
* `value` - The progress value,
* `color` - hex [`#000000` ~ `#ffffff`] of the current bar
* }
*/
multiValues: PropTypes.arrayOf(
PropTypes.shape({
/**
* The progress bar current value.
*/
value: PropTypes.number.isRequired,
/**
* The bar color in hex - #000000 ~ #ffffff
*/
color: PropTypes.string.isRequired
}).isRequired
),
/** ARIA description for the progress bar */
ariaLabel: PropTypes.string
};
LinearProgressBar.defaultProps = {
barStyle: PROGRESS_BAR_STYLES.PRIMARY,
size: SIZES.SMALL,
className: "",
multi: false,
indicateProgress: false,
valueSecondary: 0,
value: 0,
min: 0,
max: 100,
animated: true,
multiValues: [],
ariaLabel: ""
};
export default LinearProgressBar;