Files
svsmspcalc/theme-manager.js
2026-03-16 01:42:17 -04:00

116 lines
3.6 KiB
JavaScript

(function(global) {
'use strict';
const THEME_STORAGE_KEY = 'svs-theme';
const THEME_STYLESHEET_ID = 'themeStylesheetLink';
const THEME_ASSET_VERSION = '20260313-02';
const SVG_SUN = '<span class="fa-icon fa-icon-sun-bright fa-icon--theme" style="--icon-size:17px;"></span>';
const SVG_MOON = '<span class="fa-icon fa-icon-moon-stars fa-icon--theme" style="--icon-size:15px;"></span>';
const SVG_GLASS = '<span class="fa-icon fa-icon-sparkles fa-icon--theme" style="--icon-size:16px;"></span>';
const THEME_ORDER = ['dark', 'light', 'glass'];
const THEME_CONFIG = {
dark: {
icon: SVG_MOON,
href: null,
label: 'Dark'
},
light: {
icon: SVG_SUN,
href: 'SVS-MSP-Calculator-light.css',
label: 'Light'
},
glass: {
icon: SVG_GLASS,
href: 'SVS-MSP-Calculator-glass.css',
label: 'Glass'
}
};
function getSavedTheme() {
const saved = localStorage.getItem(THEME_STORAGE_KEY);
return THEME_ORDER.includes(saved) ? saved : 'dark';
}
function getCurrentTheme() {
const applied = document.documentElement.dataset.theme;
return THEME_ORDER.includes(applied) ? applied : getSavedTheme();
}
function updateThemeToggleUi(theme) {
const icon = document.getElementById('themeToggleIcon');
const btn = document.getElementById('themeToggle');
const currentIndex = THEME_ORDER.indexOf(theme);
const nextTheme = THEME_ORDER[(currentIndex + 1) % THEME_ORDER.length];
const currentLabel = THEME_CONFIG[theme].label;
const nextLabel = THEME_CONFIG[nextTheme].label;
if (icon) icon.innerHTML = THEME_CONFIG[theme].icon;
if (btn) {
const uiLabel = `Theme: ${currentLabel}. Click to switch to ${nextLabel}.`;
btn.setAttribute('title', uiLabel);
btn.setAttribute('aria-label', uiLabel);
}
}
function applyTheme(theme) {
const nextTheme = THEME_ORDER.includes(theme) ? theme : 'dark';
const existing = document.getElementById(THEME_STYLESHEET_ID);
const legacyLight = document.getElementById('lightThemeLink');
if (existing) existing.remove();
if (legacyLight) legacyLight.remove();
const themeHref = THEME_CONFIG[nextTheme].href;
if (themeHref) {
const el = document.createElement('link');
el.id = THEME_STYLESHEET_ID;
el.rel = 'stylesheet';
el.href = `${themeHref}?v=${THEME_ASSET_VERSION}`;
el.dataset.theme = nextTheme;
document.head.appendChild(el);
}
document.documentElement.dataset.theme = nextTheme;
localStorage.setItem(THEME_STORAGE_KEY, nextTheme);
updateThemeToggleUi(nextTheme);
}
function toggleTheme() {
const currentTheme = getCurrentTheme();
const currentIndex = THEME_ORDER.indexOf(currentTheme);
const nextTheme = THEME_ORDER[(currentIndex + 1) % THEME_ORDER.length];
// Enable brief color transition for smooth theme swap
document.body.classList.add('theme-transitioning');
applyTheme(nextTheme);
setTimeout(function() {
document.body.classList.remove('theme-transitioning');
}, 300);
}
function initTheme() {
applyTheme(getSavedTheme());
}
global.SVSQuoteTheme = {
THEME_STORAGE_KEY,
THEME_STYLESHEET_ID,
THEME_ASSET_VERSION,
THEME_ORDER,
THEME_CONFIG,
getSavedTheme,
getCurrentTheme,
updateThemeToggleUi,
applyTheme,
toggleTheme,
initTheme
};
global.getSavedTheme = getSavedTheme;
global.getCurrentTheme = getCurrentTheme;
global.updateThemeToggleUi = updateThemeToggleUi;
global.applyTheme = applyTheme;
global.toggleTheme = toggleTheme;
global.initTheme = initTheme;
})(window);