UNPKG

@carbon/react

Version:

React components for the Carbon Design System

153 lines (149 loc) 4.81 kB
/** * 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. */ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js'; import React, { useRef } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { ErrorFilled, CheckmarkFilled } from '@carbon/icons-react'; import { useId } from '../../internal/useId.js'; import { usePrefix } from '../../internal/usePrefix.js'; import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js'; function ProgressBar({ className, helperText, hideLabel, label, max = 100, size = 'big', status = 'active', type = 'default', value }) { const labelId = useId('progress-bar'); const helperId = useId('progress-bar-helper'); const helperTextId = useId('progress-bar-helper-text'); const prefix = 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) { StatusIcon = /*#__PURE__*/React.forwardRef(function ErrorFilled16(props, ref) { return /*#__PURE__*/React.createElement(ErrorFilled, _extends({ ref: ref, size: 16 }, props)); }); } else if (isFinished) { StatusIcon = /*#__PURE__*/React.forwardRef(function CheckmarkFilled16(props, ref) { return /*#__PURE__*/React.createElement(CheckmarkFilled, _extends({ ref: ref, size: 16 }, props)); }); } const ref = useRef(null); useIsomorphicEffect(() => { 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 }; export { ProgressBar as default };