// 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;
};
}
}
}