Fix: cssVars API not working correctly on Booker Timeslot selection page (#8296)

* Use a method out of react scope to set CSS vars as that doesnt need react

* Refactor
pull/8356/head
Hariom Balhara 2023-04-18 18:23:46 +05:30 committed by GitHub
parent 585e36793a
commit 6fd64b2209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 89 additions and 56 deletions

View File

@ -5,7 +5,6 @@ import Head from "next/head";
import Script from "next/script";
import "@calcom/embed-core/src/embed-iframe";
import { useEmbedUiConfig } from "@calcom/embed-core/src/embed-iframe";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
import { trpc } from "@calcom/trpc/react";
@ -28,17 +27,6 @@ const calFont = localFont({
function MyApp(props: AppProps) {
const { Component, pageProps, err, router } = props;
let pageStatus = "200";
const { cssVarsPerTheme } = useEmbedUiConfig();
const cssVarsStyle = [];
if (cssVarsPerTheme) {
for (const [themeName, cssVars] of Object.entries(cssVarsPerTheme)) {
cssVarsStyle.push(`.${themeName} {`);
for (const [cssVarName, value] of Object.entries(cssVars)) {
cssVarsStyle.push(`--${cssVarName}: ${value};`);
}
cssVarsStyle.push(`}`);
}
}
if (router.pathname === "/404") {
pageStatus = "404";
@ -76,11 +64,6 @@ function MyApp(props: AppProps) {
}
`}</style>
<style jsx global>
{`
${cssVarsStyle.join("")}
`}
</style>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
</Head>

View File

@ -1,6 +1,5 @@
import type { DocumentContext, DocumentProps } from "next/document";
import Document, { Head, Html, Main, NextScript } from "next/document";
import Script from "next/script";
import { z } from "zod";
import { getDirFromLang } from "@calcom/lib/i18n";
@ -42,7 +41,6 @@ class MyDocument extends Document<Props> {
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#000000" />
<meta name="msapplication-TileColor" content="#ff0000" />
<meta name="theme-color" content="var(--cal-bg)" />
<Script src="/embed-init-iframe.js" strategy="beforeInteractive" />
</Head>
<body

View File

@ -1,26 +0,0 @@
const calEmbedMode = typeof new URL(document.URL).searchParams.get("embed") === "string";
/* Iframe Name */
window.name.includes("cal-embed");
window.isEmbed = () => {
// Once an embed mode always an embed mode
return calEmbedMode;
};
window.resetEmbedStatus = () => {
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.sessionStorage.removeItem("calEmbedMode");
} catch (e) {}
};
window.getEmbedTheme = () => {
const url = new URL(document.URL);
return url.searchParams.get("theme");
};
window.getEmbedNamespace = () => {
const url = new URL(document.URL);
const namespace = url.searchParams.get("embed");
return namespace;
};

View File

@ -0,0 +1,55 @@
export default function EmbedInitIframe() {
if (typeof window === "undefined" || window.isEmbed) {
return;
}
const calEmbedMode = typeof new URL(document.URL).searchParams.get("embed") === "string";
/* Iframe Name */
window.name.includes("cal-embed");
window.isEmbed = () => {
// Once an embed mode always an embed mode
return calEmbedMode;
};
window.resetEmbedStatus = () => {
try {
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
window.sessionStorage.removeItem("calEmbedMode");
} catch (e) {}
};
window.getEmbedTheme = () => {
const url = new URL(document.URL);
return url.searchParams.get("theme") as "light" | "dark" | null;
};
window.getEmbedNamespace = () => {
const url = new URL(document.URL);
const namespace = url.searchParams.get("embed");
return namespace;
};
window.CalEmbed = window.CalEmbed || {};
window.CalEmbed.applyCssVars = (cssVarsPerTheme) => {
const cssVarsStyle = [];
if (cssVarsPerTheme) {
for (const [themeName, cssVars] of Object.entries(cssVarsPerTheme)) {
cssVarsStyle.push(`.${themeName} {`);
for (const [cssVarName, value] of Object.entries(cssVars)) {
cssVarsStyle.push(`--${cssVarName}: ${value};`);
}
cssVarsStyle.push(`}`);
}
}
const style = document.createElement("style");
style.id = "embed-css-vars";
style.innerText = cssVarsStyle.join("\n");
if (document.head.querySelector("#embed-css-vars")) {
return;
}
document.head.appendChild(style);
};
}

View File

@ -174,20 +174,20 @@
If you render booking embed in me, I won't restrict you. The entire page is yours. Content is by
default aligned center
</div>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{eventTypeListItem:{backgroundColor:'blue'}}})})()">
Change <code>eventTypeListItem</code> bg color
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{body:{background:'red'}}})})()">
Change <code>body</code> bg color
</button>
<button
onclick="(function () {Cal.ns.second('ui', {cssVarsPerTheme:{light:{'cal-border-booker':'green', 'cal-border-booker-width':'20px'},dark:{'cal-border-booker':'red', 'cal-border-booker-width':'5px'}}})})()">
Change booker border for dark and light themes
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'left'}})})()">Align left</button>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{eventTypeListItem:{backgroundColor:'blue'}}})})()">
Change <code>eventTypeListItem</code> bg color[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{body:{background:'red'}}})})()">
Change <code>body</code> bg color[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'left'}})})()">Align left[Deprecated]</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'center'}})})()">
Align Center
Align Center[Deprecated]
</button>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{enabledDateButton: {
@ -196,7 +196,7 @@
disabledDateButton: {
backgroundColor: generateRandomHexColor(),
},}})})()">
Change 'enabledDateButton` and `disabledDateButton` background Color
Change 'enabledDateButton` and `disabledDateButton` background Color[Deprecated]
</button>
</div>
</div>

View File

@ -2,6 +2,8 @@ import { useRouter } from "next/router";
import type { CSSProperties } from "react";
import { useState, useEffect } from "react";
import embedInit from "@calcom/embed-core/embed-iframe-init";
import type { Message } from "./embed";
import { sdkActionManager } from "./sdk-event";
@ -40,9 +42,10 @@ declare global {
CalEmbed: {
__logQueue?: unknown[];
embedStore: typeof embedStore;
applyCssVars: (cssVarsPerTheme: UiConfig["cssVarsPerTheme"]) => void;
};
CalComPageStatus: string;
isEmbed: () => boolean;
isEmbed?: () => boolean;
resetEmbedStatus: () => void;
getEmbedNamespace: () => string | null;
getEmbedTheme: () => "dark" | "light" | null;
@ -303,6 +306,11 @@ const methods = {
// Set the value here so that if setUiConfig state isn't available and later it's defined,it uses this value
embedStore.uiConfig = uiConfig;
if (uiConfig.cssVarsPerTheme) {
window.CalEmbed.applyCssVars(uiConfig.cssVarsPerTheme);
}
if (embedStore.setUiConfig) {
embedStore.setUiConfig(uiConfig);
}
@ -423,6 +431,8 @@ function keepParentInformedAboutDimensionChanges() {
if (isBrowser) {
log("Embed SDK loaded", { isEmbed: window?.isEmbed?.() || false });
// Exposes certain global variables/fns that are used by the app to get interface with the embed.
embedInit();
const url = new URL(document.URL);
embedStore.theme = (window?.getEmbedTheme?.() || "auto") as UiConfig["theme"];
if (url.searchParams.get("prerender") !== "true" && window?.isEmbed?.()) {

View File

@ -20,6 +20,19 @@ function App() {
action: "*",
callback,
});
api("ui", {
cssVarsPerTheme: {
light: {
"cal-border-booker": "red",
"cal-border-booker-width": "20px",
},
dark: {
"cal-border-booker": "red",
"cal-border-booker-width": "5px",
},
},
});
});
return () => {
api.then((api) => {