@carbon/react
Version:
React components for the Carbon Design System
164 lines (162 loc) • 5.99 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 { Text } from "../Text/Text.js";
import { Enter, Space } from "../../internal/keyboard/keys.js";
import { matches } from "../../internal/keyboard/match.js";
import classNames from "classnames";
import React from "react";
import PropTypes from "prop-types";
import { jsx, jsxs } from "react/jsx-runtime";
import { CheckmarkOutline, CircleDash, Incomplete, Warning } from "@carbon/icons-react";
//#region src/components/ProgressIndicator/ProgressIndicator.tsx
/**
* 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.
*/
const translationIds = {
"carbon.progress-step.complete": "carbon.progress-step.complete",
"carbon.progress-step.incomplete": "carbon.progress-step.incomplete",
"carbon.progress-step.current": "carbon.progress-step.current",
"carbon.progress-step.invalid": "carbon.progress-step.invalid"
};
const defaultTranslations = {
[translationIds["carbon.progress-step.complete"]]: "Complete",
[translationIds["carbon.progress-step.incomplete"]]: "Incomplete",
[translationIds["carbon.progress-step.current"]]: "Current",
[translationIds["carbon.progress-step.invalid"]]: "Invalid"
};
const defaultTranslateWithId = (messageId) => {
return defaultTranslations[messageId];
};
function ProgressIndicator({ children, className: customClassName, currentIndex: controlledIndex = 0, onChange, spaceEqually, vertical, ...rest }) {
const prefix = usePrefix();
return /* @__PURE__ */ jsx("ul", {
className: classNames({
[`${prefix}--progress`]: true,
[`${prefix}--progress--vertical`]: vertical,
[`${prefix}--progress--space-equal`]: spaceEqually && !vertical,
[customClassName ?? ""]: customClassName
}),
...rest,
children: React.Children.map(children, (child, index) => {
if (!React.isValidElement(child)) return null;
const onClick = onChange ? () => onChange(index) : void 0;
if (index === controlledIndex) return React.cloneElement(child, {
complete: child.props.complete,
current: !child.props.complete,
index,
onClick
});
if (index < controlledIndex) return React.cloneElement(child, {
complete: true,
index,
onClick
});
if (index > controlledIndex) return React.cloneElement(child, {
complete: child.props.complete || false,
index,
onClick
});
return null;
})
});
}
ProgressIndicator.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
currentIndex: PropTypes.number,
onChange: PropTypes.func,
spaceEqually: PropTypes.bool,
vertical: PropTypes.bool
};
function ProgressStep({ label, description, className, current, complete, invalid, secondaryLabel, disabled, onClick, translateWithId: t = defaultTranslateWithId, ...rest }) {
const prefix = usePrefix();
const classes = classNames({
[`${prefix}--progress-step`]: true,
[`${prefix}--progress-step--current`]: current,
[`${prefix}--progress-step--complete`]: complete,
[`${prefix}--progress-step--incomplete`]: !complete && !current,
[`${prefix}--progress-step--disabled`]: disabled,
[className ?? ""]: className
});
const handleKeyDown = (e) => {
if (matches(e, [Enter, Space]) && onClick) onClick(e);
};
const SVGIcon = ({ complete, current, description, invalid, prefix }) => {
if (invalid) return /* @__PURE__ */ jsx(Warning, {
className: `${prefix}--progress__warning`,
children: /* @__PURE__ */ jsx("title", { children: description })
});
if (current) return /* @__PURE__ */ jsx(Incomplete, { children: /* @__PURE__ */ jsx("title", { children: description }) });
if (complete) return /* @__PURE__ */ jsx(CheckmarkOutline, { children: /* @__PURE__ */ jsx("title", { children: description }) });
return /* @__PURE__ */ jsx(CircleDash, { children: /* @__PURE__ */ jsx("title", { children: description }) });
};
let message = t("carbon.progress-step.incomplete");
if (current) message = t("carbon.progress-step.current");
if (complete) message = t("carbon.progress-step.complete");
if (invalid) message = t("carbon.progress-step.invalid");
return /* @__PURE__ */ jsx("li", {
className: classes,
children: /* @__PURE__ */ jsxs("button", {
type: "button",
className: classNames(`${prefix}--progress-step-button`, { [`${prefix}--progress-step-button--unclickable`]: !onClick || current }),
disabled,
"aria-disabled": disabled,
tabIndex: disabled ? -1 : 0,
onClick: !current ? onClick : void 0,
onKeyDown: handleKeyDown,
title: label,
...rest,
children: [
/* @__PURE__ */ jsx(SVGIcon, {
complete,
current,
description,
invalid,
prefix
}),
/* @__PURE__ */ jsxs("div", {
className: `${prefix}--progress-text`,
children: [/* @__PURE__ */ jsx(Text, {
as: "span",
className: `${prefix}--progress-label`,
children: label
}), secondaryLabel !== null && secondaryLabel !== void 0 ? /* @__PURE__ */ jsx(Text, {
as: "span",
className: `${prefix}--progress-optional`,
children: secondaryLabel
}) : null]
}),
/* @__PURE__ */ jsx("span", {
className: `${prefix}--assistive-text`,
children: message
}),
/* @__PURE__ */ jsx("span", { className: `${prefix}--progress-line` })
]
})
});
}
ProgressStep.propTypes = {
className: PropTypes.string,
complete: PropTypes.bool,
current: PropTypes.bool,
description: PropTypes.string,
disabled: PropTypes.bool,
index: PropTypes.number,
invalid: PropTypes.bool,
label: PropTypes.node.isRequired,
onClick: PropTypes.func,
overflowTooltipProps: PropTypes.object,
secondaryLabel: PropTypes.string,
tooltipId: PropTypes.string,
translateWithId: PropTypes.func
};
//#endregion
export { ProgressIndicator, ProgressStep };