@carbon/react
Version:
React components for the Carbon Design System
222 lines (218 loc) • 6.98 kB
JavaScript
/**
* 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 from 'react';
import PropTypes from 'prop-types';
import Button from '../Button/Button.js';
import '../Button/Button.Skeleton.js';
import ButtonSet from '../ButtonSet/ButtonSet.js';
import cx from 'classnames';
import { usePrefix } from '../../internal/usePrefix.js';
import { noopFn } from '../../internal/noopFn.js';
import InlineLoading from '../InlineLoading/InlineLoading.js';
function SecondaryButtonSet({
secondaryButtons,
secondaryButtonText,
secondaryClassName,
closeModal,
onRequestClose,
disabled
}) {
function handleRequestClose(evt) {
closeModal(evt);
onRequestClose(evt);
}
if (Array.isArray(secondaryButtons) && secondaryButtons.length <= 2) {
return /*#__PURE__*/React.createElement(React.Fragment, null, secondaryButtons.map(({
buttonText,
onClick: onButtonClick
}, i) => /*#__PURE__*/React.createElement(Button, {
key: `${buttonText}-${i}`,
className: secondaryClassName,
kind: "secondary",
onClick: onButtonClick || handleRequestClose
}, buttonText)));
}
if (secondaryButtonText) {
return /*#__PURE__*/React.createElement(Button, {
disabled: disabled,
className: secondaryClassName,
onClick: handleRequestClose,
kind: "secondary"
}, 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 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 = /*#__PURE__*/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 = cx(`${prefix}--modal-footer`, customClassName, Array.isArray(secondaryButtons) && secondaryButtons.length === 2 ? `${prefix}--modal-footer--three-button` : null);
const primaryButtonClass = cx(primaryClassName, loadingStatus !== 'inactive' ? `${prefix}--btn--loading` : null);
const loadingActive = loadingStatus !== 'inactive';
const secondaryButtonProps = {
closeModal,
secondaryButtons,
secondaryButtonText,
secondaryClassName,
onRequestClose,
disabled: loadingActive
};
return /*#__PURE__*/React.createElement(ButtonSet, _extends({
className: footerClass
}, rest, {
// @ts-expect-error: Invalid derived types, will be fine once explicit types are added
ref: ref,
"aria-busy": loadingActive
}), /*#__PURE__*/React.createElement(SecondaryButtonSet, secondaryButtonProps), primaryButtonText && /*#__PURE__*/React.createElement(Button, {
onClick: onRequestSubmit,
className: primaryButtonClass,
disabled: loadingActive || primaryButtonDisabled,
kind: danger ? 'danger' : 'primary',
ref: inputref
}, loadingStatus === 'inactive' ? primaryButtonText : /*#__PURE__*/React.createElement(InlineLoading, {
status: loadingStatus,
description: loadingDescription,
iconDescription: loadingIconDescription,
className: `${prefix}--inline-loading--btn`,
onSuccess: onLoadingSuccess
})), children);
});
ModalFooter.propTypes = {
/**
* Pass in content that will be rendered in the Modal Footer
*/
children: PropTypes.node,
/**
* Specify a custom className to be applied to the Modal Footer container
*/
className: PropTypes.string,
/**
* Specify an optional function that is called whenever the modal is closed
*/
closeModal: PropTypes.func,
/**
* Specify whether the primary button should be replaced with danger button.
* Note that this prop is not applied if you render primary/danger button by yourself
*/
danger: PropTypes.bool,
/**
* The `ref` callback for the primary button.
*/
inputref: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
current: PropTypes.any
})]),
/**
* Specify the description for the loading text
*/
loadingDescription: PropTypes.string,
/**
* Specify the description for the loading text
*/
loadingIconDescription: PropTypes.string,
/**
* loading status
*/
loadingStatus: PropTypes.oneOf(['inactive', 'active', 'finished', 'error']),
/**
* Provide an optional handler to be invoked when loading is
* successful
*/
onLoadingSuccess: PropTypes.func,
/**
* Specify an optional function for when the modal is requesting to be
* closed
*/
onRequestClose: PropTypes.func,
/**
* Specify an optional function for when the modal is requesting to be
* submitted
*/
onRequestSubmit: PropTypes.func,
/**
* Specify whether the primary button should be disabled
*/
primaryButtonDisabled: PropTypes.bool,
/**
* Specify the text for the primary button
*/
primaryButtonText: PropTypes.string,
/**
* Specify a custom className to be applied to the primary button
*/
primaryClassName: PropTypes.string,
/**
* Specify the text for the secondary button
*/
secondaryButtonText: PropTypes.string,
/**
* Specify an array of config objects for secondary buttons
* (`Array<{
* buttonText: string,
* onClick: function,
* }>`).
*/
secondaryButtons: (props, propName, componentName) => {
if (props.secondaryButtons) {
if (!Array.isArray(props.secondaryButtons) || props.secondaryButtons.length !== 2) {
return 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;
},
/**
* Specify a custom className to be applied to the secondary button
*/
secondaryClassName: PropTypes.string
};
export { ModalFooter };