2023-04-27 19:56:56 +02:00
|
|
|
const themeField = document.getElementById("theme")
|
|
|
|
var DEFAULT_THEME = {}
|
|
|
|
var THEMES = [] // initialized in initTheme from data in css
|
2022-10-18 16:48:56 +02:00
|
|
|
|
|
|
|
function getThemeName(theme) {
|
2023-04-27 19:56:56 +02:00
|
|
|
theme = theme.replace("theme-", "")
|
|
|
|
theme = theme
|
|
|
|
.split("-")
|
|
|
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
|
|
.join(" ")
|
|
|
|
return theme
|
2022-10-18 16:48:56 +02:00
|
|
|
}
|
|
|
|
// init themefield
|
|
|
|
function initTheme() {
|
|
|
|
Array.from(document.styleSheets)
|
2023-04-27 19:56:56 +02:00
|
|
|
.filter((sheet) => sheet.href?.startsWith(window.location.origin))
|
|
|
|
.flatMap((sheet) => Array.from(sheet.cssRules))
|
|
|
|
.forEach((rule) => {
|
|
|
|
var selector = rule.selectorText
|
2022-11-18 03:13:08 +01:00
|
|
|
if (selector && selector.startsWith(".theme-") && !selector.includes(" ")) {
|
2023-04-27 19:56:56 +02:00
|
|
|
if (DEFAULT_THEME) {
|
|
|
|
// re-add props that dont change (css needs this so they update correctly)
|
2022-12-22 01:03:52 +01:00
|
|
|
Array.from(DEFAULT_THEME.rule.style)
|
2023-04-27 19:56:56 +02:00
|
|
|
.filter((cssVariable) => !Array.from(rule.style).includes(cssVariable))
|
|
|
|
.forEach((cssVariable) => {
|
|
|
|
rule.style.setProperty(cssVariable, DEFAULT_THEME.rule.style.getPropertyValue(cssVariable))
|
|
|
|
})
|
2022-12-22 01:03:52 +01:00
|
|
|
}
|
2023-04-27 19:56:56 +02:00
|
|
|
var theme_key = selector.substring(1)
|
2022-10-18 16:48:56 +02:00
|
|
|
THEMES.push({
|
|
|
|
key: theme_key,
|
|
|
|
name: getThemeName(theme_key),
|
|
|
|
rule: rule
|
|
|
|
})
|
|
|
|
}
|
|
|
|
if (selector && selector == ":root") {
|
|
|
|
DEFAULT_THEME = {
|
|
|
|
key: "theme-default",
|
|
|
|
name: "Default",
|
|
|
|
rule: rule
|
2023-04-27 19:56:56 +02:00
|
|
|
}
|
2022-10-18 16:48:56 +02:00
|
|
|
}
|
2023-04-27 19:56:56 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
THEMES.forEach((theme) => {
|
|
|
|
var new_option = document.createElement("option")
|
|
|
|
new_option.setAttribute("value", theme.key)
|
|
|
|
new_option.innerText = theme.name
|
|
|
|
themeField.appendChild(new_option)
|
|
|
|
})
|
2022-10-20 06:12:01 +02:00
|
|
|
|
|
|
|
// setup the style transitions a second after app initializes, so initial style is instant
|
|
|
|
setTimeout(() => {
|
2023-04-27 19:56:56 +02:00
|
|
|
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)
|
2022-10-18 16:48:56 +02:00
|
|
|
}
|
2023-04-27 19:56:56 +02:00
|
|
|
initTheme()
|
2022-10-18 16:48:56 +02:00
|
|
|
|
|
|
|
function themeFieldChanged() {
|
2023-04-27 19:56:56 +02:00
|
|
|
var theme_key = themeField.value
|
|
|
|
|
|
|
|
var body = document.querySelector("body")
|
|
|
|
body.classList.remove(...THEMES.map((theme) => theme.key))
|
|
|
|
body.classList.add(theme_key)
|
2022-10-18 16:48:56 +02:00
|
|
|
|
2023-04-27 19:56:56 +02:00
|
|
|
//
|
2022-10-18 16:48:56 +02:00
|
|
|
|
2023-04-27 19:56:56 +02:00
|
|
|
body.style = ""
|
|
|
|
var theme = THEMES.find((t) => t.key == theme_key)
|
2022-11-27 21:49:23 +01:00
|
|
|
let borderColor = undefined
|
2022-10-18 16:48:56 +02:00
|
|
|
if (theme) {
|
2023-04-27 19:56:56 +02:00
|
|
|
borderColor = theme.rule.style.getPropertyValue("--input-border-color").trim()
|
|
|
|
if (!borderColor.startsWith("#")) {
|
|
|
|
borderColor = theme.rule.style.getPropertyValue("--theme-color-fallback")
|
2022-11-27 21:49:23 +01:00
|
|
|
}
|
|
|
|
} else {
|
2023-04-27 19:56:56 +02:00
|
|
|
borderColor = DEFAULT_THEME.rule.style.getPropertyValue("--theme-color-fallback")
|
2022-10-18 16:48:56 +02:00
|
|
|
}
|
2022-11-27 21:49:23 +01:00
|
|
|
document.querySelector('meta[name="theme-color"]').setAttribute("content", borderColor)
|
2022-10-18 16:48:56 +02:00
|
|
|
}
|
|
|
|
|
2023-04-27 19:56:56 +02:00
|
|
|
themeField.addEventListener("change", themeFieldChanged)
|