@carbon/react
Version:
React components for the Carbon Design System
159 lines (153 loc) • 5.17 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
;
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var React = require('react');
var PropTypes = require('prop-types');
var cx = require('classnames');
var iconsReact = require('@carbon/icons-react');
var useId = require('../../internal/useId.js');
var usePrefix = require('../../internal/usePrefix.js');
var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
function ProgressBar({
className,
helperText,
hideLabel,
label,
max = 100,
size = 'big',
status = 'active',
type = 'default',
value
}) {
const labelId = useId.useId('progress-bar');
const helperId = useId.useId('progress-bar-helper');
const helperTextId = useId.useId('progress-bar-helper-text');
const prefix = usePrefix.usePrefix();
const isFinished = status === 'finished';
const isError = status === 'error';
const indeterminate = !isFinished && !isError && (value === null || value === undefined);
let cappedValue = value;
if (cappedValue && cappedValue > max) {
cappedValue = max;
}
if (cappedValue && cappedValue < 0) {
cappedValue = 0;
}
if (isError) {
cappedValue = 0;
} else if (isFinished) {
cappedValue = max;
}
const percentage = (cappedValue ?? NaN) / max;
const wrapperClasses = cx(`${prefix}--progress-bar`, `${prefix}--progress-bar--${size}`, `${prefix}--progress-bar--${type}`, {
[`${prefix}--progress-bar--indeterminate`]: indeterminate,
[`${prefix}--progress-bar--finished`]: isFinished,
[`${prefix}--progress-bar--error`]: isError
}, className);
const labelClasses = cx(`${prefix}--progress-bar__label`, {
[`${prefix}--visually-hidden`]: hideLabel
});
let StatusIcon = null;
if (isError) {
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
StatusIcon = /*#__PURE__*/React.forwardRef((props, ref) => {
return /*#__PURE__*/React.createElement(iconsReact.ErrorFilled, _rollupPluginBabelHelpers.extends({
ref: ref,
size: 16
}, props));
});
} else if (isFinished) {
// eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
StatusIcon = /*#__PURE__*/React.forwardRef((props, ref) => {
return /*#__PURE__*/React.createElement(iconsReact.CheckmarkFilled, _rollupPluginBabelHelpers.extends({
ref: ref,
size: 16
}, props));
});
}
const ref = React.useRef(null);
useIsomorphicEffect.default(() => {
if (ref.current) {
if (!isFinished && !isError) {
ref.current.style.transform = `scaleX(${percentage})`;
} else {
ref.current.style.transform = '';
}
}
}, [percentage, isFinished, isError]);
return /*#__PURE__*/React.createElement("div", {
className: wrapperClasses
}, /*#__PURE__*/React.createElement("div", {
className: labelClasses,
id: labelId
}, /*#__PURE__*/React.createElement("span", {
className: `${prefix}--progress-bar__label-text`
}, label), StatusIcon && /*#__PURE__*/React.createElement(StatusIcon, {
className: `${prefix}--progress-bar__status-icon`
})), /*#__PURE__*/React.createElement("div", {
className: `${prefix}--progress-bar__track`,
role: "progressbar",
"aria-busy": !isFinished,
"aria-invalid": isError,
"aria-labelledby": labelId,
"aria-describedby": helperText ? helperTextId : undefined,
"aria-valuemin": !indeterminate ? 0 : undefined,
"aria-valuemax": !indeterminate ? max : undefined,
"aria-valuenow": !indeterminate ? cappedValue : undefined
}, /*#__PURE__*/React.createElement("div", {
className: `${prefix}--progress-bar__bar`,
ref: ref
})), helperText && /*#__PURE__*/React.createElement("div", {
id: helperTextId,
className: `${prefix}--progress-bar__helper-text`
}, helperText, /*#__PURE__*/React.createElement("div", {
className: `${prefix}--visually-hidden`,
"aria-live": "polite",
id: helperId
}, isFinished ? 'Done' : 'Loading')));
}
ProgressBar.propTypes = {
/**
* Additional CSS class names.
*/
className: PropTypes.string,
/**
* The current progress as a textual representation.
*/
helperText: PropTypes.string,
/**
* Whether the label should be visually hidden.
*/
hideLabel: PropTypes.bool,
/**
* A label describing the progress bar.
*/
label: PropTypes.string.isRequired,
/**
* The maximum value.
*/
max: PropTypes.number,
/**
* Specify the size of the ProgressBar.
*/
size: PropTypes.oneOf(['small', 'big']),
/**
* Specify the status.
*/
status: PropTypes.oneOf(['active', 'finished', 'error']),
/**
* Defines the alignment variant of the progress bar.
*/
type: PropTypes.oneOf(['default', 'inline', 'indented']),
/**
* The current value.
*/
value: PropTypes.number
};
exports.default = ProgressBar;