@carbon/ibm-products
Version:
Carbon for IBM Products
146 lines (144 loc) • 5.71 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 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 { getDevtoolsProps } from "../../global/js/utils/devtools.js";
import { clamp } from "../../global/js/utils/clamp.js";
import { InterstitialScreenContext, blockClass } from "./context.js";
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
import PropTypes from "prop-types";
import { Button, ButtonSet, InlineLoading, ModalFooter, usePrefix } from "@carbon/react";
import { ArrowRight } from "@carbon/react/icons";
//#region src/components/InterstitialScreen/InterstitialScreenFooter.tsx
/**
* Copyright IBM Corp. 2024, 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.
*/
const InterstitialScreenFooter = React.forwardRef((props, ref) => {
const { className = "", skipButtonLabel = "Skip", previousButtonLabel = "Back", nextButtonLabel = "Next", startButtonLabel = "Get Started", actionButtonRenderer, onAction, ...rest } = props;
const footerBlockClass = `${blockClass}--footer`;
const { handleClose, progStep, handleGotoStep, stepCount, disableButtonConfig, isFullScreen } = useContext(InterstitialScreenContext);
const startButtonRef = useRef(null);
const nextButtonRef = useRef(null);
const [loadingAction, setLoadingAction] = useState("");
const carbonPrefix = usePrefix();
const isMultiStep = !!stepCount && stepCount > 1;
const progStepFloor = 0;
const progStepCeil = stepCount - 1;
useEffect(() => {
if (progStep + 1 === stepCount && startButtonRef.current) startButtonRef.current.focus();
}, [progStep]);
const handleAction = async (actionType) => {
setLoadingAction(actionType);
const abortContinue = await onAction?.(actionType, {
handleGotoStep,
progStep,
stepCount,
disableButtonConfig
});
setLoadingAction("");
if (abortContinue) return;
if (actionType === "next" || actionType === "back") {
const targetStep = clamp(progStep + (actionType === "next" ? 1 : -1), progStepFloor, progStepCeil);
handleGotoStep?.(targetStep);
} else handleClose?.(actionType);
};
const handleStart = () => handleAction("start");
const handleSkip = () => handleAction("skip");
const handleClickNext = () => handleAction("next");
const handleClickPrev = () => handleAction("back");
const getRenderIcon = useMemo(() => {
if (loadingAction !== "start" && isMultiStep && progStep === progStepCeil) return { renderIcon: ArrowRight };
return {};
}, [
loadingAction,
isMultiStep,
progStep,
progStepCeil
]);
const getFooterContent = () => /* @__PURE__ */ React.createElement(ButtonSet, null, isMultiStep && skipButtonLabel !== "" && /* @__PURE__ */ React.createElement(Button, {
className: `${blockClass}--skip-btn`,
kind: "ghost",
size: "lg",
title: skipButtonLabel,
onClick: handleSkip,
disabled: disableButtonConfig?.skip
}, skipButtonLabel, loadingAction === "skip" && /* @__PURE__ */ React.createElement(InlineLoading, null)), isMultiStep && progStep > 0 && /* @__PURE__ */ React.createElement(Button, {
className: `${blockClass}--prev-btn`,
kind: "secondary",
size: "lg",
title: previousButtonLabel,
disabled: disableButtonConfig?.back,
onClick: handleClickPrev
}, previousButtonLabel, loadingAction === "back" && /* @__PURE__ */ React.createElement(InlineLoading, null)), isMultiStep && progStep < progStepCeil && /* @__PURE__ */ React.createElement(Button, {
className: `${blockClass}--next-btn`,
renderIcon: loadingAction !== "next" ? ArrowRight : void 0,
ref: nextButtonRef,
size: "lg",
title: nextButtonLabel,
disabled: disableButtonConfig?.next,
onClick: handleClickNext
}, nextButtonLabel, loadingAction === "next" && /* @__PURE__ */ React.createElement(InlineLoading, null)), (isMultiStep && progStep === progStepCeil || !isMultiStep) && /* @__PURE__ */ React.createElement(Button, {
className: `${blockClass}--start-btn`,
ref: startButtonRef,
size: "lg",
title: startButtonLabel,
disabled: disableButtonConfig?.start,
onClick: handleStart,
...getRenderIcon
}, startButtonLabel, loadingAction === "start" && /* @__PURE__ */ React.createElement(InlineLoading, null)));
const footerContent = actionButtonRenderer ? actionButtonRenderer({
handleGotoStep,
progStep,
stepCount,
disableButtonConfig
}) : getFooterContent();
return isFullScreen ? /* @__PURE__ */ React.createElement("div", {
ref,
className: `${footerBlockClass} ${className} ${carbonPrefix}--modal-footer`,
...getDevtoolsProps("InterstitialScreenFooter"),
...rest
}, footerContent) : /* @__PURE__ */ React.createElement(ModalFooter, {
className: `${footerBlockClass} ${className}`,
ref,
...rest
}, footerContent);
});
InterstitialScreenFooter.propTypes = {
/**
* This is an optional callback prop that allows to render your custom footer action buttons.
*/
actionButtonRenderer: PropTypes.func,
/**
* Provide an optional class to be applied to the containing node.
*/
className: PropTypes.string,
/**
* The label for the Next button.
*/
nextButtonLabel: PropTypes.string,
/**
* optional asynchronous callback on action button click (skip, previous, next and start)
* note: this is applicable when not using custom actionButtonRenderer
*/
onAction: PropTypes.func,
/**
* The label for the Previous button.
*
*/
previousButtonLabel: PropTypes.string,
/**
* The label for the skip button.
*/
skipButtonLabel: PropTypes.string,
/**
* The label for the start button.
*/
startButtonLabel: PropTypes.string
};
//#endregion
export { InterstitialScreenFooter as default };