const themeToggle = document.createElement('template')
themeToggle.innerHTML = `
`
class ThemeToggle extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
}).append(themeToggle.content.cloneNode(true))
this.isChecked = false
this.hasTheme = 'light'
this.toggleState = this.toggleState.bind(this)
this.fireEvent = this.fireEvent.bind(this)
this.handleThemeChange = this.handleThemeChange.bind(this)
}
static get observedAttributes() {
return ['checked'];
}
daylight() {
this.hasTheme = 'light'
document.body.dataset.theme = 'light'
this.setAttribute('aria-checked', 'false')
}
nightlight() {
this.hasTheme = 'dark'
document.body.dataset.theme = 'dark'
this.setAttribute('aria-checked', 'true')
}
toggleState() {
this.toggleAttribute('checked')
this.fireEvent()
}
handleKeyDown(e) {
if (e.code === 'Space') {
this.toggleState()
}
}
handleThemeChange(e) {
if (e.detail.theme !== this.hasTheme) {
if (e.detail.theme === 'dark') {
this.setAttribute('checked', '')
}
else {
this.removeAttribute('checked')
}
}
}
fireEvent() {
this.dispatchEvent(
new CustomEvent('themechange', {
bubbles: true,
composed: true,
detail: {
theme: this.hasTheme
}
})
)
}
connectedCallback() {
this.setAttribute('role', 'switch')
this.setAttribute('aria-label', 'theme toggle')
if (localStorage.getItem(`${window.location.hostname}-theme`) === "dark") {
this.nightlight();
this.setAttribute('checked', '')
} else if (localStorage.getItem(`${window.location.hostname}-theme`) === "light") {
this.daylight();
this.removeAttribute('checked')
}
else {
if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) {
this.nightlight();
this.setAttribute('checked', '')
} else {
this.daylight();
this.removeAttribute('checked')
}
}
this.addEventListener("click", this.toggleState);
this.addEventListener("keydown", this.handleKeyDown);
document.addEventListener('themechange', this.handleThemeChange)
}
disconnectedCallback() {
this.removeEventListener("click", this.toggleState);
this.removeEventListener("keydown", this.handleKeyDown);
document.removeEventListener('themechange', this.handleThemeChange)
}
attributeChangedCallback(name, oldVal, newVal) {
if (name === 'checked') {
if (this.hasAttribute('checked')) {
this.nightlight();
localStorage.setItem(`${window.location.hostname}-theme`, "dark");
} else {
this.daylight();
localStorage.setItem(`${window.location.hostname}-theme`, "light");
}
}
}
}
window.customElements.define('theme-toggle', ThemeToggle);