// Lit import { html, nothing } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; import { customElement, property, state } from "lit/decorators.js"; // Utils / Services import { AiPriseLitElement } from "../utils/aiprise-element.js"; // Typescript import { DetailedHTMLProps, HTMLAttributes } from "react"; import { AiPriseErrorEvent, AiPriseSessionEvent, AiPriseBusinessProfileEvent, AiPriseDataSavedEvent, } from "../types/aiprise-session-event.js"; import { AiPriseElementProps } from "../types/aiprise-element-props.js"; // Colors, Icons & Style import assets from "../assets.js"; import { buttonResetStyle } from "../styles/button-reset.js"; // Components import "lit-portal"; @customElement("aiprise-button") export class AiPriseButton extends AiPriseLitElement { // 1 - PROPS @property({ type: String }) title = "Verify with AiPrise"; @property({ type: String, attribute: "text-color" }) textColor: string | undefined; // 2 - STATE @state() iframeHasError = false; @state() iframeIsSuccessful = false; // When user fully completes the form @state() iframeVisible = false; @state() iframeVerificationSessionId = ""; // 3 - FUNCTIONS handleButtonClick = () => { this.iframeVisible = true; }; handleCloseClick = () => { // If iframe has error OR when form is fully filled, close without confirmation if (this.iframeHasError) { this.iframeVisible = false; return; } if (this.iframeIsSuccessful) { this.dispatchContinueAndResetState(this.iframeVerificationSessionId); return; } // If iframe doesn't have error or isn't completed, ask for confirmation first const shouldClose = confirm("Are you sure you want to cancel your verification?"); if (shouldClose) { this.iframeVisible = false; this.dispatchAbandoned(this.iframeVerificationSessionId); } }; setIframeSessionIdAndDispatchStarted = (e: AiPriseSessionEvent) => { this.iframeVerificationSessionId = e.detail.verification_session_id; this.dispatchStarted(e); }; setIframeSuccessfulAndDispatchSuccessful = (e: AiPriseSessionEvent) => { this.iframeIsSuccessful = true; this.dispatchSuccessful(e); }; dispatchContinueAndResetState = (e: AiPriseSessionEvent | string) => { this.dispatchContinue(e); this.iframeHasError = false; this.iframeIsSuccessful = false; this.iframeVisible = false; this.iframeVerificationSessionId = ""; }; setIframeErrorAndDispatchError = (e: AiPriseErrorEvent | string) => { this.iframeHasError = true; this.dispatchError(e); }; // 4 - CSS & HTML render() { const buttonColor = this.color ?? assets.colors.aiprise; const textColor = this.textColor ?? "#ffffff"; return html` ${buttonResetStyle} ${this.iframeVisible ? html`
`} >
` : nothing} `; } } // Typescript declare global { interface HTMLElementTagNameMap { "aiprise-button": AiPriseButton; } interface HTMLElementEventMap { "aiprise:started": AiPriseSessionEvent; "aiprise:resumed": AiPriseSessionEvent; "aiprise:business-profile": AiPriseBusinessProfileEvent; "aiprise:data-saved": AiPriseDataSavedEvent; "aiprise:data-restored": AiPriseSessionEvent; "aiprise:successful": AiPriseSessionEvent; "aiprise:continue": AiPriseSessionEvent; "aiprise:completed": AiPriseSessionEvent; // DEPRECATED: Keeping for backward compatibility "aiprise:abandoned": AiPriseSessionEvent; } // For React namespace JSX { interface IntrinsicElements { "aiprise-button": DetailedHTMLProps, HTMLElement> & AiPriseElementProps & { title?: string; color?: string; "text-color"?: string; }; } } }