diff --git a/packages/embeds/embed-core/playwright/lib/testUtils.ts b/packages/embeds/embed-core/playwright/lib/testUtils.ts index f83f8e41b1..7e991d4c38 100644 --- a/packages/embeds/embed-core/playwright/lib/testUtils.ts +++ b/packages/embeds/embed-core/playwright/lib/testUtils.ts @@ -1,4 +1,5 @@ -import { Page, Frame, test, expect } from "@playwright/test"; +import type { Page, Frame } from "@playwright/test"; +import { test, expect } from "@playwright/test"; import prisma from "@calcom/prisma"; @@ -38,7 +39,7 @@ export const getEmbedIframe = async ({ page, pathname }: { page: Page; pathname: const iframeReady = await page.evaluate(() => { return new Promise((resolve) => { const interval = setInterval(() => { - const iframe = document.querySelector(".cal-embed") as HTMLIFrameElement | null; + const iframe = document.querySelector(".cal-embed"); // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore if (iframe && iframe.contentWindow && window.iframeReady) { diff --git a/packages/embeds/embed-core/src/FloatingButton/FloatingButton.ts b/packages/embeds/embed-core/src/FloatingButton/FloatingButton.ts index ca50655dcf..a1a2604881 100644 --- a/packages/embeds/embed-core/src/FloatingButton/FloatingButton.ts +++ b/packages/embeds/embed-core/src/FloatingButton/FloatingButton.ts @@ -22,31 +22,31 @@ export class FloatingButton extends HTMLElement { attributeChangedCallback(name: string, oldValue: string, newValue: string) { if (name === "data-button-text") { - const buttonEl = this.shadowRoot?.querySelector("#button"); + const buttonEl = this.shadowRoot?.querySelector("#button"); if (!buttonEl) { throw new Error("Button not found"); } buttonEl.innerHTML = newValue; } else if (name === "data-hide-button-icon") { - const buttonIconEl = this.shadowRoot?.querySelector("#button-icon") as HTMLElement; + const buttonIconEl = this.shadowRoot?.querySelector("#button-icon"); if (!buttonIconEl) { throw new Error("Button not found"); } buttonIconEl.style.display = newValue == "true" ? "none" : "block"; } else if (name === "data-button-position") { - const buttonEl = this.shadowRoot?.querySelector("button") as HTMLElement; + const buttonEl = this.shadowRoot?.querySelector("button"); if (!buttonEl) { throw new Error("Button not found"); } buttonEl.className = FloatingButton.updatedClassString(newValue, buttonEl.className); } else if (name === "data-button-color") { - const buttonEl = this.shadowRoot?.querySelector("button") as HTMLElement; + const buttonEl = this.shadowRoot?.querySelector("button"); if (!buttonEl) { throw new Error("Button not found"); } buttonEl.style.backgroundColor = newValue; } else if (name === "data-button-text-color") { - const buttonEl = this.shadowRoot?.querySelector("button") as HTMLElement; + const buttonEl = this.shadowRoot?.querySelector("button"); if (!buttonEl) { throw new Error("Button not found"); } diff --git a/packages/embeds/embed-core/src/Inline/inline.ts b/packages/embeds/embed-core/src/Inline/inline.ts index a191948ed5..309913982d 100644 --- a/packages/embeds/embed-core/src/Inline/inline.ts +++ b/packages/embeds/embed-core/src/Inline/inline.ts @@ -11,13 +11,13 @@ export class Inline extends HTMLElement { attributeChangedCallback(name: string, oldValue: string, newValue: string) { if (name === "loading") { if (newValue == "done") { - (this.shadowRoot!.querySelector(".loader")! as HTMLElement).style.display = "none"; + this.shadowRoot!.querySelector(".loader")!.style.display = "none"; } else if (newValue === "failed") { - (this.shadowRoot!.querySelector(".loader")! as HTMLElement).style.display = "none"; - (this.shadowRoot!.querySelector("#error")! as HTMLElement).style.display = "block"; - (this.shadowRoot!.querySelector("slot")! as HTMLElement).style.visibility = "hidden"; + this.shadowRoot!.querySelector(".loader")!.style.display = "none"; + this.shadowRoot!.querySelector("#error")!.style.display = "block"; + this.shadowRoot!.querySelector("slot")!.style.visibility = "hidden"; const errorString = getErrorString(this.dataset.errorCode); - (this.shadowRoot!.querySelector("#error")! as HTMLElement).innerText = errorString; + this.shadowRoot!.querySelector("#error")!.innerText = errorString; } } } diff --git a/packages/embeds/embed-core/src/ModalBox/ModalBox.ts b/packages/embeds/embed-core/src/ModalBox/ModalBox.ts index e72ae30597..12c85e4679 100644 --- a/packages/embeds/embed-core/src/ModalBox/ModalBox.ts +++ b/packages/embeds/embed-core/src/ModalBox/ModalBox.ts @@ -76,7 +76,7 @@ export class ModalBox extends HTMLElement { connectedCallback() { this.assertHasShadowRoot(); - const closeEl = this.shadowRoot.querySelector(".close") as HTMLElement; + const closeEl = this.shadowRoot.querySelector(".close"); document.addEventListener( "keydown", (e) => { @@ -92,9 +92,11 @@ export class ModalBox extends HTMLElement { this.close(); }); - closeEl.onclick = () => { - this.close(); - }; + if (closeEl) { + closeEl.onclick = () => { + this.close(); + }; + } } constructor() { diff --git a/packages/embeds/embed-core/src/embed-iframe.ts b/packages/embeds/embed-core/src/embed-iframe.ts index 26c61f38fb..fa088e0107 100644 --- a/packages/embeds/embed-core/src/embed-iframe.ts +++ b/packages/embeds/embed-core/src/embed-iframe.ts @@ -330,12 +330,16 @@ function keepParentInformedAboutDimensionChanges() { // Use the dimensions of main element as in most places there is max-width restriction on it and we just want to show the main content. // It avoids the unwanted padding outside main tag. const mainElement = - (document.getElementsByClassName("main")[0] as HTMLElement) || + document.getElementsByClassName("main")[0] || document.getElementsByTagName("main")[0] || document.documentElement; const documentScrollHeight = document.documentElement.scrollHeight; const documentScrollWidth = document.documentElement.scrollWidth; + if (!(mainElement instanceof HTMLElement)) { + throw new Error("Main element should be an HTMLElement"); + } + const contentHeight = mainElement.offsetHeight; const contentWidth = mainElement.offsetWidth; @@ -415,14 +419,14 @@ if (isBrowser) { }); document.addEventListener("click", (e) => { - if (!e.target) { + if (!e.target || !(e.target instanceof Node)) { return; } const mainElement = - (document.getElementsByClassName("main")[0] as HTMLElement) || + document.getElementsByClassName("main")[0] || document.getElementsByTagName("main")[0] || document.documentElement; - if ((e.target as HTMLElement).contains(mainElement)) { + if (e.target.contains(mainElement)) { sdkActionManager?.fire("__closeIframe", {}); } }); diff --git a/packages/embeds/embed-core/src/embed.ts b/packages/embeds/embed-core/src/embed.ts index 6cfb2ab22e..253b004fba 100644 --- a/packages/embeds/embed-core/src/embed.ts +++ b/packages/embeds/embed-core/src/embed.ts @@ -305,27 +305,32 @@ export class Cal { // }, // }, // }); - let attributesString = ""; - let existingEl = null; + let existingEl: HTMLElement | null = null; + if (attributes?.id) { - attributesString += ` id="${attributes.id}"`; existingEl = document.getElementById(attributes.id); } - let el = existingEl; + let el: HTMLElement; if (!existingEl) { - const template = document.createElement("template"); - template.innerHTML = ``; - el = template.content.children[0] as HTMLElement; - document.body.appendChild(template.content); + el = document.createElement("cal-floating-button"); + el.dataset.calLink = calLink; + el.dataset.calNamespace = this.namespace; + if (attributes?.id) { + el.id = attributes.id; + } + + document.body.appendChild(el); + } else { + el = existingEl; } if (buttonText) { - el!.setAttribute("data-button-text", buttonText); + el.setAttribute("data-button-text", buttonText); } - el!.setAttribute("data-hide-button-icon", "" + hideButtonIcon); - el!.setAttribute("data-button-position", "" + buttonPosition); - el!.setAttribute("data-button-color", "" + buttonColor); - el!.setAttribute("data-button-text-color", "" + buttonTextColor); + el.setAttribute("data-hide-button-icon", "" + hideButtonIcon); + el.setAttribute("data-button-position", "" + buttonPosition); + el.setAttribute("data-button-color", "" + buttonColor); + el.setAttribute("data-button-text-color", "" + buttonTextColor); } modal({ calLink, config = {}, uid }: { calLink: string; config?: Record; uid: number }) { diff --git a/packages/embeds/embed-core/src/preview.ts b/packages/embeds/embed-core/src/preview.ts index 1516579651..2bd84c63ad 100644 --- a/packages/embeds/embed-core/src/preview.ts +++ b/packages/embeds/embed-core/src/preview.ts @@ -77,7 +77,7 @@ previewWindow.addEventListener("message", (e) => { globalCal(data.instruction.name, data.instruction.arg); } if (data.type == "inlineEmbedDimensionUpdate") { - const inlineEl = document.querySelector("#my-embed") as HTMLElement; + const inlineEl = document.querySelector("#my-embed"); if (inlineEl) { inlineEl.style.width = data.data.width; inlineEl.style.height = data.data.height;