diff --git a/.changeset/modern-seas-smile.md b/.changeset/modern-seas-smile.md new file mode 100644 index 0000000..3c7ee8d --- /dev/null +++ b/.changeset/modern-seas-smile.md @@ -0,0 +1,5 @@ +--- +"mode-watcher": minor +--- + +feat: add ability to disable head script injection via the `disableHeadScriptInjection` prop for handling in hooks.server files diff --git a/packages/mode-watcher/src/lib/index.ts b/packages/mode-watcher/src/lib/index.ts index c046a3e..d0ab467 100644 --- a/packages/mode-watcher/src/lib/index.ts +++ b/packages/mode-watcher/src/lib/index.ts @@ -1,4 +1,5 @@ import { + generateSetInitialModeExpression, mode, modeStorageKey, resetMode, @@ -12,6 +13,7 @@ import { } from "./mode.js"; export { + generateSetInitialModeExpression, setMode, toggleMode, resetMode, diff --git a/packages/mode-watcher/src/lib/mode-watcher-full.svelte b/packages/mode-watcher/src/lib/mode-watcher-full.svelte new file mode 100644 index 0000000..27252cf --- /dev/null +++ b/packages/mode-watcher/src/lib/mode-watcher-full.svelte @@ -0,0 +1,23 @@ + + + + {#if themeColors} + + + + + {/if} + + {@html `(` + + setInitialMode.toString() + + `)(` + + JSON.stringify(initConfig) + + `);`} + diff --git a/packages/mode-watcher/src/lib/mode-watcher-lite.svelte b/packages/mode-watcher/src/lib/mode-watcher-lite.svelte new file mode 100644 index 0000000..36c323b --- /dev/null +++ b/packages/mode-watcher/src/lib/mode-watcher-lite.svelte @@ -0,0 +1,12 @@ + + +{#if themeColors} + + + + +{/if} diff --git a/packages/mode-watcher/src/lib/mode-watcher.svelte b/packages/mode-watcher/src/lib/mode-watcher.svelte index 0fbda02..874f905 100644 --- a/packages/mode-watcher/src/lib/mode-watcher.svelte +++ b/packages/mode-watcher/src/lib/mode-watcher.svelte @@ -4,7 +4,6 @@ defineConfig, disableTransitions as disableTransitionsStore, mode, - setInitialMode, setMode, setTheme, systemPrefersMode, @@ -20,6 +19,8 @@ modeStorageKey as modeStorageKeyStore, themeStorageKey as themeStorageKeyStore, } from "./stores.js"; + import ModeWatcherLite from "./mode-watcher-lite.svelte"; + import ModeWatcherFull from "./mode-watcher-full.svelte"; type $$Props = ModeWatcherProps; @@ -33,6 +34,7 @@ export let nonce: string = ""; export let themeStorageKey: string = "mode-watcher-theme"; export let modeStorageKey: string = "mode-watcher-mode"; + export let disableHeadScriptInjection = false; $: disableTransitionsStore.set(disableTransitions); $: themeColorsStore.set(themeColors); @@ -70,18 +72,8 @@ $: trueNonce = typeof window === "undefined" ? nonce : ""; - - {#if themeColors} - - - - - {/if} - - - {@html `(` + - setInitialMode.toString() + - `)(` + - JSON.stringify(initConfig) + - `);`} - +{#if disableHeadScriptInjection} + +{:else} + +{/if} diff --git a/packages/mode-watcher/src/lib/mode.ts b/packages/mode-watcher/src/lib/mode.ts index 8fa223f..54a2f5b 100644 --- a/packages/mode-watcher/src/lib/mode.ts +++ b/packages/mode-watcher/src/lib/mode.ts @@ -37,24 +37,24 @@ export function defineConfig(config: SetInitialModeArgs) { } type SetInitialModeArgs = { - defaultMode: Mode; + defaultMode?: Mode; themeColors?: ThemeColors; - darkClassNames: string[]; - lightClassNames: string[]; - defaultTheme: string; - modeStorageKey: string; - themeStorageKey: string; + darkClassNames?: string[]; + lightClassNames?: string[]; + defaultTheme?: string; + modeStorageKey?: string; + themeStorageKey?: string; }; /** Used to set the mode on initial page load to prevent FOUC */ export function setInitialMode({ - defaultMode, + defaultMode = "system", themeColors, darkClassNames = ["dark"], lightClassNames = [], defaultTheme = "", - modeStorageKey, - themeStorageKey, + modeStorageKey = "mode-watcher-mode", + themeStorageKey = "mode-watcher-theme", }: SetInitialModeArgs) { const rootEl = document.documentElement; const mode = localStorage.getItem(modeStorageKey) || defaultMode; @@ -89,6 +89,13 @@ export function setInitialMode({ localStorage.setItem(modeStorageKey, mode); } +/** + * A type-safe way to generate the source expression used to set the initial mode and avoid FOUC. + */ +export function generateSetInitialModeExpression(config: SetInitialModeArgs = {}): string { + return `(${setInitialMode.toString()})(${JSON.stringify(config)});`; +} + export { modeStorageKey, themeStorageKey, diff --git a/packages/mode-watcher/src/lib/types.ts b/packages/mode-watcher/src/lib/types.ts index 13add5f..e8ca0cd 100644 --- a/packages/mode-watcher/src/lib/types.ts +++ b/packages/mode-watcher/src/lib/types.ts @@ -77,4 +77,12 @@ export type ModeWatcherProps = { * @defaultValue `undefined` */ nonce?: string; + + /** + * Whether to disable the injected script tag that sets the initial mode. + * Set this if you are manually injecting the script using a hook. + * + * @defaultValue `false` + */ + disableHeadScriptInjection?: boolean; }; diff --git a/sites/docs/content/api-reference/mode-watcher.md b/sites/docs/content/api-reference/mode-watcher.md index fd81911..debfdad 100644 --- a/sites/docs/content/api-reference/mode-watcher.md +++ b/sites/docs/content/api-reference/mode-watcher.md @@ -172,5 +172,13 @@ export type ModeWatcherProps = { * @defaultValue `undefined` */ nonce?: string; + + /** + * Whether to disable the injected script tag that sets the initial mode. + * Set this if you are manually injecting the script using a hook. + * + * @defaultValue `false` + */ + disableHeadScriptInjection?: boolean; }; ````