import { DOCUMENT } from '@angular/common'; import { effect, inject, Injectable, signal } from '@angular/core'; export type ThemePreference = 'light' | 'dark' | 'system'; const THEME_STORAGE_KEY = 'lmnp-theme'; @Injectable({ providedIn: 'root' }) export class ThemeService { private readonly document = inject(DOCUMENT); private readonly colorSchemeQuery = typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-color-scheme: dark)') : null; private readonly systemUsesDark = signal(this.colorSchemeQuery?.matches ?? false); readonly preference = signal(this.readPreference()); constructor() { this.colorSchemeQuery?.addEventListener('change', (event) => this.systemUsesDark.set(event.matches), ); effect(() => { const preference = this.preference(); const resolvedTheme = preference === 'system' ? (this.systemUsesDark() ? 'dark' : 'light') : preference; localStorage.setItem(THEME_STORAGE_KEY, preference); this.document.documentElement.dataset['theme'] = resolvedTheme; this.document.documentElement.dataset['themePreference'] = preference; }); } setPreference(preference: ThemePreference): void { this.preference.set(preference); } private readPreference(): ThemePreference { const storedPreference = localStorage.getItem(THEME_STORAGE_KEY); return storedPreference === 'dark' || storedPreference === 'system' ? storedPreference : 'light'; } }