@carbon/react
Version:
React components for the Carbon Design System
127 lines (125 loc) • 4.26 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2026
*
* 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 { usePrefix } from "../../internal/usePrefix.js";
import useIsomorphicEffect from "../../internal/useIsomorphicEffect.js";
import { useId } from "../../internal/useId.js";
import classNames from "classnames";
import React, { useRef } from "react";
import PropTypes from "prop-types";
import { jsx, jsxs } from "react/jsx-runtime";
import { CheckmarkFilled, ErrorFilled } from "@carbon/icons-react";
//#region src/components/ProgressBar/ProgressBar.tsx
/**
* Copyright IBM Corp. 2021
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
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 === void 0);
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 = classNames(`${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 = classNames(`${prefix}--progress-bar__label`, { [`${prefix}--visually-hidden`]: hideLabel });
let StatusIcon = null;
if (isError) StatusIcon = React.forwardRef((props, ref) => {
return /* @__PURE__ */ jsx(ErrorFilled, {
ref,
size: 16,
...props
});
});
else if (isFinished) StatusIcon = React.forwardRef((props, ref) => {
return /* @__PURE__ */ jsx(CheckmarkFilled, {
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__ */ jsxs("div", {
className: wrapperClasses,
children: [
/* @__PURE__ */ jsxs("div", {
className: labelClasses,
id: labelId,
children: [/* @__PURE__ */ jsx("span", {
className: `${prefix}--progress-bar__label-text`,
children: label
}), StatusIcon && /* @__PURE__ */ jsx(StatusIcon, { className: `${prefix}--progress-bar__status-icon` })]
}),
/* @__PURE__ */ jsx("div", {
className: `${prefix}--progress-bar__track`,
role: "progressbar",
"aria-busy": !isFinished,
"aria-invalid": isError,
"aria-labelledby": labelId,
"aria-describedby": helperText ? helperTextId : void 0,
"aria-valuemin": !indeterminate ? 0 : void 0,
"aria-valuemax": !indeterminate ? max : void 0,
"aria-valuenow": !indeterminate ? cappedValue : void 0,
children: /* @__PURE__ */ jsx("div", {
className: `${prefix}--progress-bar__bar`,
ref
})
}),
helperText && /* @__PURE__ */ jsxs("div", {
id: helperTextId,
className: `${prefix}--progress-bar__helper-text`,
children: [helperText, /* @__PURE__ */ jsx("div", {
className: `${prefix}--visually-hidden`,
"aria-live": "polite",
id: helperId,
children: isFinished ? "Done" : "Loading"
})]
})
]
});
}
ProgressBar.propTypes = {
className: PropTypes.string,
helperText: PropTypes.string,
hideLabel: PropTypes.bool,
label: PropTypes.string.isRequired,
max: PropTypes.number,
size: PropTypes.oneOf(["small", "big"]),
status: PropTypes.oneOf([
"active",
"finished",
"error"
]),
type: PropTypes.oneOf([
"default",
"inline",
"indented"
]),
value: PropTypes.number
};
//#endregion
export { ProgressBar as default };