diff --git a/.changeset/tasty-yaks-leave.md b/.changeset/tasty-yaks-leave.md new file mode 100644 index 0000000..fda5295 --- /dev/null +++ b/.changeset/tasty-yaks-leave.md @@ -0,0 +1,6 @@ +--- +"fogbender": minor +"fogbender-react": minor +--- + +Dark/light mode switch diff --git a/packages/fogbender-react/src/index.tsx b/packages/fogbender-react/src/index.tsx index 266a9bd..77bc9da 100644 --- a/packages/fogbender-react/src/index.tsx +++ b/packages/fogbender-react/src/index.tsx @@ -119,7 +119,8 @@ export const FogbenderConfig: React.FC<{ clientUrl?: string; env?: Env; token: Token | undefined; -}> = ({ clientUrl, env, token }) => { + mode?: "light" | "dark"; +}> = ({ clientUrl, env, token, mode = "light" }) => { const fogbender = useFogbender(); React.useEffect(() => { fogbender.setClientUrl(clientUrl); @@ -139,6 +140,9 @@ export const FogbenderConfig: React.FC<{ fogbender.setToken(undefined); }; }, [token]); + React.useEffect(() => { + fogbender.setMode(mode); + }, [mode]); return null; }; diff --git a/packages/fogbender/package.json b/packages/fogbender/package.json index ba5aaab..0fc04bf 100644 --- a/packages/fogbender/package.json +++ b/packages/fogbender/package.json @@ -66,7 +66,7 @@ "dist" ], "dependencies": { - "solid-js": "^1.2.6", + "solid-js": "1.8.0", "twind": "^0.16.16" } } diff --git a/packages/fogbender/src/createIframe.ts b/packages/fogbender/src/createIframe.ts index 6a7857f..849d847 100644 --- a/packages/fogbender/src/createIframe.ts +++ b/packages/fogbender/src/createIframe.ts @@ -50,6 +50,7 @@ export function renderIframe( headless, disableFit, onVisitorInfo, + initialMode = () => "light", }: { rootEl: HTMLElement; env: Env | undefined; @@ -58,9 +59,11 @@ export function renderIframe( onVisitorInfo: (info: VisitorInfo, reload: boolean) => void; headless?: boolean; disableFit?: boolean; + initialMode: () => "dark" | "light"; }, openWindow: () => void ) { + let _mode = initialMode(); const iFrame = document.createElement("iframe"); iFrame.src = url; @@ -82,7 +85,7 @@ export function renderIframe( return; } if (e.data?.type === "APP_IS_READY") { - iFrame.contentWindow?.postMessage({ env, initToken: token, headless }, url); + iFrame.contentWindow?.postMessage({ env, initToken: token, headless, mode: _mode }, url); iFrame.contentWindow?.postMessage( { notificationsPermission: window.Notification?.permission }, url @@ -173,13 +176,21 @@ export function renderIframe( iFrame.style.height = height + "px"; } + function setMode(mode: "light" | "dark") { + _mode = mode; + iFrame.contentWindow?.postMessage({ mode }, url); + } + adaptIFrame(); new ResizeSensor(rootEl, adaptIFrame); new ResizeSensor(document.body, adaptIFrame); window.addEventListener("resize", adaptIFrame); - return () => { - iFrame.src = "about:blank"; - rootEl.removeChild(iFrame); + return { + setIframeMode: setMode, + cleanup: () => { + iFrame.src = "about:blank"; + rootEl.removeChild(iFrame); + }, }; } diff --git a/packages/fogbender/src/index.ts b/packages/fogbender/src/index.ts index 0499003..48f216f 100644 --- a/packages/fogbender/src/index.ts +++ b/packages/fogbender/src/index.ts @@ -23,9 +23,10 @@ export const createNewFogbender = (): Fogbender => { env: undefined as Env | undefined, token: undefined as Token | undefined, url: defaultUrl as string | undefined, - iframe: undefined as HTMLIFrameElement | undefined, events: createEvents(), chatWindow: null as null | Window, + mode: "light" as "light" | "dark", + setIframeMode: undefined as ((mode: "light" | "dark") => void) | undefined, }; const openWindow = () => { if (!state.chatWindow || state.chatWindow.closed) { @@ -67,6 +68,13 @@ export const createNewFogbender = (): Fogbender => { updateConfigured(); return fogbender; }, + async setMode(mode) { + state.mode = mode; + if (state.setIframeMode) { + state.setIframeMode(mode); + } + return fogbender; + }, async setToken(token) { const tokenCheck = checkToken(token); // true means bad @@ -134,14 +142,19 @@ export const createNewFogbender = (): Fogbender => { storeVisitorInfo(info); if (reload) { cleanup(); - cleanup = rerender(); + const { cleanup: cleanup2, setIframeMode } = rerender(); + state.setIframeMode = setIframeMode; + cleanup = cleanup2; } }, + initialMode: () => state.mode, }, openWindow ); }; - let cleanup = rerender(); + const { cleanup: cleanup0, setIframeMode } = rerender(); + state.setIframeMode = setIframeMode; + let cleanup = cleanup0; return () => { cleanup(); }; @@ -168,14 +181,19 @@ export const createNewFogbender = (): Fogbender => { storeVisitorInfo(info); if (reload) { cleanup(); - cleanup = rerender(); + const { cleanup: cleanup3, setIframeMode } = rerender(); + state.setIframeMode = setIframeMode; + cleanup = cleanup3; } }, + initialMode: () => state.mode, }, openWindow ); }; - let cleanup = rerender(); + const { cleanup: cleanup1, setIframeMode } = rerender(); + state.setIframeMode = setIframeMode; + let cleanup = cleanup1; return () => { cleanup(); }; diff --git a/packages/fogbender/src/server.ts b/packages/fogbender/src/server.ts index b6314eb..12f81cf 100644 --- a/packages/fogbender/src/server.ts +++ b/packages/fogbender/src/server.ts @@ -11,6 +11,7 @@ export const createNewFogbender = (): Fogbender => { url: undefined as string | undefined, iframe: undefined as HTMLIFrameElement | undefined, chatWindow: null as null | Window, + mode: "light" as "light" | "dark", }; const fogbender: Fogbender & { _privateData: any } = { _privateData: state, @@ -60,6 +61,10 @@ export const createNewFogbender = (): Fogbender => { async renderUnreadBadge() { return () => {}; }, + async setMode(_mode: "light" | "dark") { + state.mode = _mode; + return fogbender; + }, }; return fogbender; }; diff --git a/packages/fogbender/src/types.ts b/packages/fogbender/src/types.ts index d93f467..e892e6d 100644 --- a/packages/fogbender/src/types.ts +++ b/packages/fogbender/src/types.ts @@ -79,6 +79,7 @@ export interface Fogbender { setEnv(env: Env | undefined): Promise; setClientUrl(url: string | undefined): Promise; setToken(token: Token | undefined): Promise; + setMode(mode: "light" | "dark"): Promise; isClientConfigured(): Promise>; renderIframe(opts: { rootEl: HTMLElement;