Spaces:
Runtime error
Runtime error
const themeField = document.getElementById("theme"); | |
var DEFAULT_THEME = {}; | |
var THEMES = []; // initialized in initTheme from data in css | |
function getThemeName(theme) { | |
theme = theme.replace("theme-", ""); | |
theme = theme.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); | |
return theme; | |
} | |
// init themefield | |
function initTheme() { | |
Array.from(document.styleSheets) | |
.filter(sheet => sheet.href?.startsWith(window.location.origin)) | |
.flatMap(sheet => Array.from(sheet.cssRules)) | |
.forEach(rule => { | |
var selector = rule.selectorText; | |
if (selector && selector.startsWith(".theme-") && !selector.includes(" ")) { | |
if (DEFAULT_THEME) { // re-add props that dont change (css needs this so they update correctly) | |
Array.from(DEFAULT_THEME.rule.style) | |
.filter(cssVariable => !Array.from(rule.style).includes(cssVariable)) | |
.forEach(cssVariable => { | |
rule.style.setProperty(cssVariable, DEFAULT_THEME.rule.style.getPropertyValue(cssVariable)); | |
}); | |
} | |
var theme_key = selector.substring(1); | |
THEMES.push({ | |
key: theme_key, | |
name: getThemeName(theme_key), | |
rule: rule | |
}) | |
} | |
if (selector && selector == ":root") { | |
DEFAULT_THEME = { | |
key: "theme-default", | |
name: "Default", | |
rule: rule | |
}; | |
} | |
}); | |
THEMES.forEach(theme => { | |
var new_option = document.createElement("option"); | |
new_option.setAttribute("value", theme.key); | |
new_option.innerText = theme.name; | |
themeField.appendChild(new_option); | |
}); | |
// setup the style transitions a second after app initializes, so initial style is instant | |
setTimeout(() => { | |
var body = document.querySelector("body"); | |
var style = document.createElement('style'); | |
style.innerHTML = "* { transition: background 0.5s, color 0.5s, background-color 0.5s; }"; | |
body.appendChild(style); | |
}, 1000); | |
} | |
initTheme(); | |
function themeFieldChanged() { | |
var theme_key = themeField.value; | |
var body = document.querySelector("body"); | |
body.classList.remove(...THEMES.map(theme => theme.key)); | |
body.classList.add(theme_key); | |
// | |
body.style = ""; | |
var theme = THEMES.find(t => t.key == theme_key); | |
let borderColor = undefined | |
if (theme) { | |
borderColor = theme.rule.style.getPropertyValue('--input-border-color').trim() | |
if (!borderColor.startsWith('#')) { | |
borderColor = theme.rule.style.getPropertyValue('--theme-color-fallback') | |
} | |
} else { | |
borderColor = DEFAULT_THEME.rule.style.getPropertyValue('--theme-color-fallback') | |
} | |
document.querySelector('meta[name="theme-color"]').setAttribute("content", borderColor) | |
} | |
themeField.addEventListener('change', themeFieldChanged); | |