SHA256
50 lines
1.6 KiB
JavaScript
50 lines
1.6 KiB
JavaScript
const STORAGE_KEY = 'shine-ui-theme-mode-v1';
|
|
const MODES = new Set(['system', 'light', 'dark']);
|
|
let sessionMode = null;
|
|
|
|
function normalizeMode(value) {
|
|
const mode = String(value || '').trim().toLowerCase();
|
|
return MODES.has(mode) ? mode : 'system';
|
|
}
|
|
|
|
export function getThemeMode() {
|
|
if (sessionMode !== null) return sessionMode;
|
|
try {
|
|
return normalizeMode(localStorage.getItem(STORAGE_KEY));
|
|
} catch {
|
|
return 'system';
|
|
}
|
|
}
|
|
|
|
export function applyThemeMode(mode = getThemeMode()) {
|
|
const normalized = normalizeMode(mode);
|
|
const resolved = normalized === 'system'
|
|
? (window.matchMedia?.('(prefers-color-scheme: light)')?.matches ? 'light' : 'dark')
|
|
: normalized;
|
|
document.documentElement.dataset.themeMode = normalized;
|
|
document.documentElement.dataset.theme = resolved;
|
|
document.documentElement.style.colorScheme = resolved;
|
|
return { mode: normalized, resolved };
|
|
}
|
|
|
|
export function setThemeMode(mode) {
|
|
const normalized = normalizeMode(mode);
|
|
sessionMode = normalized;
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, normalized);
|
|
} catch {
|
|
// В приватном режиме тема всё равно применяется до закрытия страницы.
|
|
}
|
|
return applyThemeMode(normalized);
|
|
}
|
|
|
|
export function watchSystemTheme() {
|
|
const media = window.matchMedia?.('(prefers-color-scheme: light)');
|
|
if (!media) return () => {};
|
|
const onChange = () => {
|
|
if (getThemeMode() === 'system') applyThemeMode('system');
|
|
};
|
|
media.addEventListener?.('change', onChange);
|
|
return () => media.removeEventListener?.('change', onChange);
|
|
}
|