@carbon/react
Version:
React components for the Carbon Design System
140 lines (138 loc) • 5.41 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 { noopFn } from "../../internal/noopFn.js";
import Button_default from "../Button/index.js";
import ButtonSet_default from "../ButtonSet/index.js";
import InlineLoading_default from "../InlineLoading/index.js";
import classNames from "classnames";
import React from "react";
import PropTypes from "prop-types";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
//#region src/components/ComposedModal/ModalFooter.tsx
/**
* Copyright IBM Corp. 2023, 2025
*
* 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 SecondaryButtonSet({ secondaryButtons, secondaryButtonText, secondaryClassName, closeModal, onRequestClose, disabled }) {
function handleRequestClose(evt) {
closeModal(evt);
onRequestClose(evt);
}
if (Array.isArray(secondaryButtons) && secondaryButtons.length <= 2) return /* @__PURE__ */ jsx(Fragment, { children: secondaryButtons.map(({ buttonText, onClick: onButtonClick }, i) => /* @__PURE__ */ jsx(Button_default, {
className: secondaryClassName,
kind: "secondary",
onClick: onButtonClick || handleRequestClose,
children: buttonText
}, `${buttonText}-${i}`)) });
if (secondaryButtonText) return /* @__PURE__ */ jsx(Button_default, {
disabled,
className: secondaryClassName,
onClick: handleRequestClose,
kind: "secondary",
children: secondaryButtonText
});
return null;
}
SecondaryButtonSet.propTypes = {
closeModal: PropTypes.func,
disabled: PropTypes.bool,
onRequestClose: PropTypes.func,
secondaryButtonText: PropTypes.string,
secondaryButtons: (props, propName, componentName) => {
if (props.secondaryButtons) {
if (!Array.isArray(props.secondaryButtons) || props.secondaryButtons.length !== 2) return /* @__PURE__ */ new Error(`${propName} needs to be an array of two button config objects`);
const shape = {
buttonText: PropTypes.node,
onClick: PropTypes.func
};
props[propName].forEach((secondaryButton) => {
PropTypes.checkPropTypes(shape, secondaryButton, propName, componentName);
});
}
return null;
},
secondaryClassName: PropTypes.string
};
const ModalFooter = React.forwardRef(function ModalFooter({ children, className: customClassName, closeModal = noopFn, danger, inputref, onRequestClose = noopFn, onRequestSubmit = noopFn, primaryButtonDisabled, primaryButtonText, primaryClassName, secondaryButtonText, secondaryButtons, secondaryClassName, loadingStatus = "inactive", loadingDescription, loadingIconDescription, onLoadingSuccess = noopFn, ...rest }, ref) {
const prefix = usePrefix();
const footerClass = classNames(`${prefix}--modal-footer`, customClassName, Array.isArray(secondaryButtons) && secondaryButtons.length === 2 ? `${prefix}--modal-footer--three-button` : null);
const primaryButtonClass = classNames(primaryClassName, loadingStatus !== "inactive" ? `${prefix}--btn--loading` : null);
const loadingActive = loadingStatus !== "inactive";
const secondaryButtonProps = {
closeModal,
secondaryButtons,
secondaryButtonText,
secondaryClassName,
onRequestClose,
disabled: loadingActive
};
return /* @__PURE__ */ jsxs(ButtonSet_default, {
className: footerClass,
...rest,
ref,
"aria-busy": loadingActive,
children: [
/* @__PURE__ */ jsx(SecondaryButtonSet, { ...secondaryButtonProps }),
primaryButtonText && /* @__PURE__ */ jsx(Button_default, {
onClick: onRequestSubmit,
className: primaryButtonClass,
disabled: loadingActive || primaryButtonDisabled,
kind: danger ? "danger" : "primary",
ref: inputref,
children: loadingStatus === "inactive" ? primaryButtonText : /* @__PURE__ */ jsx(InlineLoading_default, {
status: loadingStatus,
description: loadingDescription,
iconDescription: loadingIconDescription,
className: `${prefix}--inline-loading--btn`,
onSuccess: onLoadingSuccess
})
}),
children
]
});
});
ModalFooter.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
closeModal: PropTypes.func,
danger: PropTypes.bool,
inputref: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({ current: PropTypes.any })]),
loadingDescription: PropTypes.string,
loadingIconDescription: PropTypes.string,
loadingStatus: PropTypes.oneOf([
"inactive",
"active",
"finished",
"error"
]),
onLoadingSuccess: PropTypes.func,
onRequestClose: PropTypes.func,
onRequestSubmit: PropTypes.func,
primaryButtonDisabled: PropTypes.bool,
primaryButtonText: PropTypes.string,
primaryClassName: PropTypes.string,
secondaryButtonText: PropTypes.string,
secondaryButtons: (props, propName, componentName) => {
if (props.secondaryButtons) {
if (!Array.isArray(props.secondaryButtons) || props.secondaryButtons.length !== 2) return /* @__PURE__ */ new Error(`${propName} needs to be an array of two button config objects`);
const shape = {
buttonText: PropTypes.node,
onClick: PropTypes.func
};
props[propName].forEach((secondaryButton) => {
PropTypes.checkPropTypes(shape, secondaryButton, propName, componentName);
});
}
return null;
},
secondaryClassName: PropTypes.string
};
//#endregion
export { ModalFooter };