From b16ad9f34997d817c3cfd2d367221da28cdd006b Mon Sep 17 00:00:00 2001 From: rxliuli Date: Sat, 4 Jan 2025 14:23:56 +0800 Subject: [PATCH] feat: support shadow dom, close https://github.com/svecosystem/mode-watcher/issues/104 --- packages/mode-watcher/src/lib/mode-watcher-full.svelte | 2 ++ packages/mode-watcher/src/lib/mode-watcher.svelte | 2 ++ packages/mode-watcher/src/lib/mode.ts | 9 ++++++++- packages/mode-watcher/src/lib/stores.ts | 4 ++-- packages/mode-watcher/src/lib/types.ts | 7 +++++++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/mode-watcher/src/lib/mode-watcher-full.svelte b/packages/mode-watcher/src/lib/mode-watcher-full.svelte index 27252cf..005630c 100644 --- a/packages/mode-watcher/src/lib/mode-watcher-full.svelte +++ b/packages/mode-watcher/src/lib/mode-watcher-full.svelte @@ -5,6 +5,8 @@ export let trueNonce: string = ""; export let initConfig: Parameters[0]; export let themeColors: ThemeColors = undefined; + + $: window.__modeWatcherTo = initConfig.to; diff --git a/packages/mode-watcher/src/lib/mode-watcher.svelte b/packages/mode-watcher/src/lib/mode-watcher.svelte index 874f905..624ffcb 100644 --- a/packages/mode-watcher/src/lib/mode-watcher.svelte +++ b/packages/mode-watcher/src/lib/mode-watcher.svelte @@ -35,6 +35,7 @@ export let themeStorageKey: string = "mode-watcher-theme"; export let modeStorageKey: string = "mode-watcher-mode"; export let disableHeadScriptInjection = false; + export let to: ModeWatcherProps["to"] = document.documentElement; $: disableTransitionsStore.set(disableTransitions); $: themeColorsStore.set(themeColors); @@ -67,6 +68,7 @@ defaultTheme, modeStorageKey, themeStorageKey, + to, }); $: trueNonce = typeof window === "undefined" ? nonce : ""; diff --git a/packages/mode-watcher/src/lib/mode.ts b/packages/mode-watcher/src/lib/mode.ts index 54a2f5b..119be22 100644 --- a/packages/mode-watcher/src/lib/mode.ts +++ b/packages/mode-watcher/src/lib/mode.ts @@ -44,8 +44,15 @@ type SetInitialModeArgs = { defaultTheme?: string; modeStorageKey?: string; themeStorageKey?: string; + to?: HTMLElement | HTMLHtmlElement | null; }; +declare global { + interface Window { + __modeWatcherTo?: HTMLElement | HTMLHtmlElement | null; + } +} + /** Used to set the mode on initial page load to prevent FOUC */ export function setInitialMode({ defaultMode = "system", @@ -56,7 +63,7 @@ export function setInitialMode({ modeStorageKey = "mode-watcher-mode", themeStorageKey = "mode-watcher-theme", }: SetInitialModeArgs) { - const rootEl = document.documentElement; + const rootEl = window.__modeWatcherTo ?? document.documentElement; const mode = localStorage.getItem(modeStorageKey) || defaultMode; const theme = localStorage.getItem(themeStorageKey) || defaultTheme; const light = diff --git a/packages/mode-watcher/src/lib/stores.ts b/packages/mode-watcher/src/lib/stores.ts index 3c41371..fd71213 100644 --- a/packages/mode-watcher/src/lib/stores.ts +++ b/packages/mode-watcher/src/lib/stores.ts @@ -208,7 +208,7 @@ function createDerivedMode() { const sanitizedLightClassNames = sanitizeClassNames($lightClassNames); function update() { - const htmlEl = document.documentElement; + const htmlEl = window.__modeWatcherTo ?? document.documentElement; const themeColorEl = document.querySelector('meta[name="theme-color"]'); if (derivedMode === "light") { if (sanitizedDarkClassNames.length) @@ -251,7 +251,7 @@ function createDerivedTheme() { if (!isBrowser) return undefined; function update() { - const htmlEl = document.documentElement; + const htmlEl = window.__modeWatcherTo ?? document.documentElement; htmlEl.setAttribute("data-theme", $theme); } diff --git a/packages/mode-watcher/src/lib/types.ts b/packages/mode-watcher/src/lib/types.ts index e8ca0cd..bcfb944 100644 --- a/packages/mode-watcher/src/lib/types.ts +++ b/packages/mode-watcher/src/lib/types.ts @@ -70,6 +70,13 @@ export type ModeWatcherProps = { */ themeStorageKey?: string; + /** + * The element to apply the mode to. + * + * @defaultValue `document.documentElement` + */ + to?: HTMLElement | HTMLHtmlElement | null; + /** * An optional nonce to use for the injected script tag to allow-list mode-watcher * if you are using a Content Security Policy.