104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
export type GuestThemePayload = {
|
|
primary: string;
|
|
secondary: string;
|
|
background: string;
|
|
surface: string;
|
|
mode?: 'light' | 'dark' | 'auto';
|
|
};
|
|
|
|
type GuestThemeCleanup = () => void;
|
|
|
|
const prefersDarkScheme = (): boolean => {
|
|
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
|
|
return false;
|
|
}
|
|
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
};
|
|
|
|
const applyColorScheme = (root: HTMLElement, theme: 'light' | 'dark') => {
|
|
if (theme === 'dark') {
|
|
root.classList.add('dark');
|
|
root.style.colorScheme = 'dark';
|
|
} else {
|
|
root.classList.remove('dark');
|
|
root.style.colorScheme = 'light';
|
|
}
|
|
};
|
|
|
|
export function applyGuestTheme(payload: GuestThemePayload): GuestThemeCleanup {
|
|
if (typeof document === 'undefined') {
|
|
return () => {};
|
|
}
|
|
|
|
const root = document.documentElement;
|
|
const hadGuestTheme = root.classList.contains('guest-theme');
|
|
const wasDark = root.classList.contains('dark');
|
|
const previousColorScheme = root.style.colorScheme;
|
|
const previousVars = {
|
|
primary: root.style.getPropertyValue('--guest-primary'),
|
|
secondary: root.style.getPropertyValue('--guest-secondary'),
|
|
background: root.style.getPropertyValue('--guest-background'),
|
|
surface: root.style.getPropertyValue('--guest-surface'),
|
|
};
|
|
|
|
root.classList.add('guest-theme');
|
|
root.style.setProperty('--guest-primary', payload.primary);
|
|
root.style.setProperty('--guest-secondary', payload.secondary);
|
|
root.style.setProperty('--guest-background', payload.background);
|
|
root.style.setProperty('--guest-surface', payload.surface);
|
|
|
|
const mode = payload.mode ?? 'auto';
|
|
if (mode === 'dark') {
|
|
applyColorScheme(root, 'dark');
|
|
} else if (mode === 'light') {
|
|
applyColorScheme(root, 'light');
|
|
} else {
|
|
applyColorScheme(root, prefersDarkScheme() ? 'dark' : 'light');
|
|
}
|
|
|
|
return () => {
|
|
if (hadGuestTheme) {
|
|
root.classList.add('guest-theme');
|
|
} else {
|
|
root.classList.remove('guest-theme');
|
|
}
|
|
|
|
if (wasDark) {
|
|
root.classList.add('dark');
|
|
} else {
|
|
root.classList.remove('dark');
|
|
}
|
|
|
|
if (previousColorScheme) {
|
|
root.style.colorScheme = previousColorScheme;
|
|
} else {
|
|
root.style.removeProperty('color-scheme');
|
|
}
|
|
|
|
if (previousVars.primary) {
|
|
root.style.setProperty('--guest-primary', previousVars.primary);
|
|
} else {
|
|
root.style.removeProperty('--guest-primary');
|
|
}
|
|
|
|
if (previousVars.secondary) {
|
|
root.style.setProperty('--guest-secondary', previousVars.secondary);
|
|
} else {
|
|
root.style.removeProperty('--guest-secondary');
|
|
}
|
|
|
|
if (previousVars.background) {
|
|
root.style.setProperty('--guest-background', previousVars.background);
|
|
} else {
|
|
root.style.removeProperty('--guest-background');
|
|
}
|
|
|
|
if (previousVars.surface) {
|
|
root.style.setProperty('--guest-surface', previousVars.surface);
|
|
} else {
|
|
root.style.removeProperty('--guest-surface');
|
|
}
|
|
};
|
|
}
|