start working version of new theme handler

This commit is contained in:
Jesse Winton
2025-04-04 13:22:10 -04:00
parent bbc73067f5
commit dcf6c1f693
6 changed files with 46 additions and 42 deletions

View File

@@ -1,8 +1,7 @@
<script lang="ts">
import Select, { type SelectOption } from './Select.svelte';
import { Select as Select2 } from '$lib/components/ui';
import { themeStore, setTheme, type Theme } from '$lib/providers/theme';
import { get } from 'svelte/store';
import { themeStore, setTheme } from '$lib/providers/theme';
const options = [
{
@@ -28,6 +27,6 @@
{options}
bind:value={$themeStore.theme}
onValueChange={(e) => {
setTheme(e as Theme);
setTheme(e);
}}
/>

View File

@@ -37,7 +37,7 @@
<div {...select.content}>
{#each options as option}
<div {...select.getOption(option.value)}>
{option}
{option.label}
</div>
{/each}
</div>

View File

@@ -1,25 +1,34 @@
import { writable } from 'svelte/store';
export type Theme = 'dark' | 'light' | 'system';
import { writable } from 'svelte/store';
export interface ThemeStore {
themes: string[];
forcedTheme?: Theme;
theme?: Theme;
resolvedTheme?: string;
systemTheme?: Omit<Theme, 'system'>;
}
export interface ThemeStore {
themes: string[];
forcedTheme?: string;
theme?: string;
resolvedTheme?: string;
systemTheme?: string;
}
export const setTheme = (theme?: Theme): void =>
themeStore.update((store) => ({ ...store, theme }));
export const themeStore = writable<ThemeStore>({
themes: [],
forcedTheme: undefined,
theme: undefined,
resolvedTheme: undefined,
systemTheme: undefined
});
// Create the theme store
export const themeStore = writable<ThemeStore>({
themes: ['light', 'dark'],
forcedTheme: undefined,
theme: undefined,
resolvedTheme: undefined,
systemTheme: undefined
});
export { default as ThemeProvider } from './theme.svelte'
export const setTheme = (theme?: string) =>
themeStore.update((store) => ({ ...store, theme }));
export const setResolvedTheme = (resolvedTheme?: string) =>
themeStore.update((store) => ({ ...store, resolvedTheme }));
export const setSystemTheme = (systemTheme?: string) =>
themeStore.update((store) => ({ ...store, systemTheme }));
export const setThemes = (themes: string[]) =>
themeStore.update((store) => ({ ...store, themes }));
export { default as ThemeProvider } from './theme.svelte';

View File

@@ -1,19 +1,19 @@
<script lang="ts">
import { colorSchemes, MEDIA } from './constants';
import { disableAnimation, getSystemTheme, getTheme } from './helpers';
import { themeStore, setTheme, type Theme } from './index';
import { themeStore, setTheme } from './index';
import ThemeScript from './theme-script.svelte';
import { browser } from '$app/environment';
interface Props {
forcedTheme?: Theme;
forcedTheme?: string;
disableTransitionOnChange?: boolean;
enableSystem?: boolean;
enableColorScheme?: boolean;
storageKey?: string;
themes?: string[];
defaultTheme?: Theme;
defaultTheme?: string;
attribute?: string | 'class';
value?: {
[themeName: string]: string;
@@ -51,13 +51,14 @@
const attrs = !value ? themes : Object.values(value);
const handleMediaQuery = (e?: MediaQueryList) => {
const systemTheme = getSystemTheme(e) as Theme;
const systemTheme = getSystemTheme(e) as string;
$themeStore.resolvedTheme = systemTheme;
$themeStore.systemTheme = systemTheme;
if (theme === 'system' && !forcedTheme) changeTheme(systemTheme, false);
if (theme === 'system' && !forcedTheme) changeTheme(systemTheme, false, true);
};
const changeTheme = (theme?: Theme, updateStorage?: boolean, updateDOM?: boolean) => {
const changeTheme = (theme?: string, updateStorage?: boolean, updateDOM?: boolean) => {
if (!theme) return;
let name = value?.[theme] || theme;
@@ -77,7 +78,7 @@
}
if (updateDOM && browser) {
const d = document.documentElement;
const d = document.body;
if (attribute === 'class') {
d.classList.remove(...(attrs as string[]));
@@ -93,20 +94,20 @@
const storageHandler = (e: StorageEvent) => {
if (e.key !== storageKey) return;
setTheme((e.newValue as Theme) || (defaultTheme as Theme));
setTheme((e.newValue as string) || (defaultTheme as string));
};
const onWindow = (window: Window) => {
const media = window.matchMedia(MEDIA);
// Intentionally use deprecated listener methods to support iOS & old browsers
media.addListener(mediaHandler);
// Use modern event listener approach
media.addEventListener('change', mediaHandler);
mediaHandler(media);
window.addEventListener('storage', storageHandler);
return {
destroy() {
window.removeEventListener('storage', storageHandler);
media.removeListener(mediaHandler);
media.removeEventListener('change', mediaHandler);
}
};
};
@@ -133,7 +134,7 @@
if (forcedTheme) {
changeTheme(theme, true, false);
} else {
changeTheme(theme);
changeTheme(theme, true, true); // Add true for updateDOM parameter
}
});
</script>

View File

@@ -132,7 +132,7 @@
>
<slot />
<ThemeProvider />
<ThemeProvider attribute="class" disableTransitionOnChange />
<style lang="scss">
:global(html) {

View File

@@ -1,5 +0,0 @@
import { Config } from 'tailwindcss';
const config = {} satisfies Config;
export default config;