UNPKG

@carbon/ibm-products-web-components

Version:
205 lines (203 loc) 8.99 kB
/** * 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 "../../globals/settings.js"; import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.127.0/helpers/decorate.js"; import "../action-set/index.js"; import { registerFocusableContainers } from "../../utilities/manageFocusTrap/manageFocusTrap.js"; import { interstitialDetailsSignal } from "./interstitial-screen-context.js"; import interstitial_screen_footer_default$1 from "./interstitial-screen-footer.scss.js"; import { html, nothing } from "lit"; import { property, state } from "lit/decorators.js"; import '@carbon/web-components/es-custom/components/button/index.js'; import HostListenerMixin from "@carbon/web-components/es/globals/mixins/host-listener.js"; import { carbonElement } from "@carbon/web-components/es/globals/decorators/carbon-element.js"; import { iconLoader } from "@carbon/web-components/es/globals/internal/icon-loader.js"; import { SignalWatcher } from "@lit-labs/signals"; import '@carbon/web-components/es-custom/components/inline-loading/inline-loading.js'; import CDSModalFooter from "@carbon/web-components/es/components/modal/modal-footer"; import ArrowRight from "@carbon/icons/es/arrow--right/16.js"; //#region src/components/interstitial-screen/interstitial-screen-footer.ts /** * @license * * Copyright IBM Corp. 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 blockClass = `c4p--interstitial-screen`; /** * interstitial-screen-footer for footer section * @element c4p-interstitial-screen-footer * @fires c4p-on-action - The name of the custom event fired just before the action. You can use this event to perform any async/sync validation. * if you pass async-action = true, the component will wait for an external listener (e.g., a form validation or confirmation modal) to resolve the proceed() * callback before continuing. When asyncAction is true, you must listen for the eventOnBeforeAction event and call the proceed() function * (either synchronously or with a promise) to allow navigation. */ let CDSInterstitialScreenFooter = class CDSInterstitialScreenFooter extends SignalWatcher(HostListenerMixin(CDSModalFooter)) { constructor(..._args) { super(..._args); this.nextButtonLabel = "Next"; this.previousButtonLabel = "Back"; this.skipButtonLabel = "Skip"; this.startButtonLabel = "Get Started"; this.slot = "footer"; this.handleSkip = () => this.handleAction("skip"); this.handleStart = () => this.handleAction("start"); this.handleClickNext = () => this.handleAction("next"); this.handleClickPrev = () => this.handleAction("back"); this.handleAction = async (actionType) => { this.loadingAction = actionType; const { currentStep, stepDetails } = interstitialDetailsSignal.get(); const stepCount = stepDetails.length; let resolvePromise; const proceedPromise = new Promise((resolve) => { resolvePromise = resolve; }); const customEvent = new CustomEvent(this.constructor.eventOnBeforeAction, { bubbles: true, composed: true, cancelable: true, detail: { step: currentStep, stepCount, proceed: (allow) => { Promise.resolve(allow).then(resolvePromise); } } }); if (!this.dispatchEvent(customEvent)) return; const canProceed = this.asyncAction ? await proceedPromise : true; this.loadingAction = ""; if (canProceed) { const { carouselAPI } = interstitialDetailsSignal.get(); if (actionType == "next") carouselAPI?.next(); else if (actionType === "back") carouselAPI?.prev(); else this._handleUserInitiatedClose?.(actionType); } }; } firstUpdated(_changedProperties) { registerFocusableContainers(this.childNodes.length > 0 ? this : this.shadowRoot); } updated(_changedProperties) { if (_changedProperties.size === 0) this.updateComplete.then(() => { const { stepDetails, currentStep } = interstitialDetailsSignal.get(); const isMultiStep = Array.isArray(stepDetails) && stepDetails.length > 0; const lastStepIndex = stepDetails?.length - 1; if (!isMultiStep) return; const focusButton = (selector) => { (this.shadowRoot?.querySelector(selector))?.focus(); }; if (currentStep === lastStepIndex) focusButton(`.c4p--interstitial-screen--start-btn`); else if (currentStep === 0) focusButton(`.c4p--interstitial-screen--next-btn`); }); } _handleUserInitiatedClose(triggeredBy) { const init = { bubbles: true, cancelable: true, composed: true, detail: { triggeredBy } }; this.dispatchEvent(new CustomEvent(this.constructor.eventRequestClose, init)); } render() { const { stepDetails, currentStep, disableActions } = interstitialDetailsSignal.get(); const { start, next, back, skip } = disableActions; const isMulti = stepDetails?.length > 0; const progStepCeil = stepDetails?.length - 1; return html`<slot> <div class="${blockClass}--footer"> <c4p-action-set size="xl"> ${isMulti ? html` <cds-custom-button class="${blockClass}--skip-btn" kind="ghost" size="xl" title="${this.skipButtonLabel}" @click="${this.handleSkip}" ?disabled="${skip}" > ${this.skipButtonLabel} </cds-custom-button> ` : ""} ${isMulti && currentStep > 0 ? html` <cds-custom-button class="${blockClass}--prev-btn" kind="secondary" size="xl" title="${this.previousButtonLabel}" ?disabled="${back}" @click="${this.handleClickPrev}" > ${this.previousButtonLabel} ${this.loadingAction === "back" ? html` <cds-custom-inline-loading slot="icon" aria-live="off"> </cds-custom-inline-loading>` : nothing} </cds-custom-button> ` : nothing} ${isMulti && currentStep < progStepCeil ? html` <cds-custom-button class="${blockClass}--next-btn" kind="primary" size="xl" title="${this.nextButtonLabel}" ?disabled="${next}" @click="${this.handleClickNext}" > ${this.nextButtonLabel} ${this.loadingAction === "next" ? html` <cds-custom-inline-loading slot="icon" aria-live="off"> </cds-custom-inline-loading>` : html`${iconLoader(ArrowRight, { slot: "icon" })}`} </cds-custom-button> ` : nothing} ${isMulti && currentStep === progStepCeil || !isMulti ? html` <cds-custom-button class="${blockClass}--start-btn" kind="primary" size="xl" title="${this.startButtonLabel}" ?disabled="${start}" @click="${this.handleStart}" > ${this.startButtonLabel} ${this.loadingAction === "start" ? html` <cds-custom-inline-loading slot="icon" aria-live="off"> </cds-custom-inline-loading>` : html`${iconLoader(ArrowRight, { slot: "icon" })}`} </cds-custom-button> ` : nothing} </c4p-action-set> </div> </slot>`; } static { this.styles = interstitial_screen_footer_default$1; } static get eventRequestClose() { return `c4p-request-close`; } /** * The name of the custom event fired just before the action. */ static get eventOnBeforeAction() { return `c4p-on-action`; } }; __decorate([property({ reflect: true })], CDSInterstitialScreenFooter.prototype, "nextButtonLabel", void 0); __decorate([property({ reflect: true })], CDSInterstitialScreenFooter.prototype, "previousButtonLabel", void 0); __decorate([property({ reflect: true })], CDSInterstitialScreenFooter.prototype, "skipButtonLabel", void 0); __decorate([property({ reflect: true })], CDSInterstitialScreenFooter.prototype, "startButtonLabel", void 0); __decorate([property({ reflect: true })], CDSInterstitialScreenFooter.prototype, "slot", void 0); __decorate([property({ type: Boolean, reflect: true, attribute: "async-action" })], CDSInterstitialScreenFooter.prototype, "asyncAction", void 0); __decorate([state()], CDSInterstitialScreenFooter.prototype, "loadingAction", void 0); CDSInterstitialScreenFooter = __decorate([carbonElement(`c4p-interstitial-screen-footer`)], CDSInterstitialScreenFooter); var interstitial_screen_footer_default = CDSInterstitialScreenFooter; //#endregion export { interstitial_screen_footer_default as default }; //# sourceMappingURL=interstitial-screen-footer.js.map