UNPKG

@carbon/react

Version:

React components for the Carbon Design System

127 lines (125 loc) 4.26 kB
/** * 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 };