116 lines
3.6 KiB
JavaScript
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);
|