86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
|
type colorScheme = 'light' | 'dark' | 'auto';
|
||
|
|
||
|
class StackColorScheme {
|
||
|
private localStorageKey = 'StackColorScheme';
|
||
|
private currentScheme: colorScheme;
|
||
|
private systemPreferScheme: colorScheme;
|
||
|
|
||
|
constructor(toggleEl: HTMLElement) {
|
||
|
this.bindMatchMedia();
|
||
|
this.currentScheme = this.getSavedScheme();
|
||
|
|
||
|
if (toggleEl)
|
||
|
this.bindClick(toggleEl);
|
||
|
|
||
|
if (document.body.style.transition == '')
|
||
|
document.body.style.setProperty('transition', 'background-color .3s ease');
|
||
|
}
|
||
|
|
||
|
private saveScheme() {
|
||
|
localStorage.setItem(this.localStorageKey, this.currentScheme);
|
||
|
}
|
||
|
|
||
|
private bindClick(toggleEl) {
|
||
|
toggleEl.addEventListener('click', (e) => {
|
||
|
if (this.isDark()) {
|
||
|
/// Disable dark mode
|
||
|
this.currentScheme = 'light';
|
||
|
}
|
||
|
else {
|
||
|
this.currentScheme = 'dark';
|
||
|
}
|
||
|
|
||
|
this.setBodyClass();
|
||
|
|
||
|
if (this.currentScheme == this.systemPreferScheme) {
|
||
|
/// Set to auto
|
||
|
this.currentScheme = 'auto';
|
||
|
}
|
||
|
|
||
|
this.saveScheme();
|
||
|
})
|
||
|
}
|
||
|
|
||
|
private isDark() {
|
||
|
return (this.currentScheme == 'dark' || this.currentScheme == 'auto' && this.systemPreferScheme == 'dark');
|
||
|
}
|
||
|
|
||
|
private dispatchEvent(colorScheme: colorScheme) {
|
||
|
const event = new CustomEvent('onColorSchemeChange', {
|
||
|
detail: colorScheme
|
||
|
});
|
||
|
window.dispatchEvent(event);
|
||
|
}
|
||
|
|
||
|
private setBodyClass() {
|
||
|
if (this.isDark()) {
|
||
|
document.body.dataset.scheme = 'dark';
|
||
|
}
|
||
|
else {
|
||
|
document.body.dataset.scheme = 'light';
|
||
|
}
|
||
|
|
||
|
this.dispatchEvent(document.body.dataset.scheme as colorScheme);
|
||
|
}
|
||
|
|
||
|
private getSavedScheme(): colorScheme {
|
||
|
const savedScheme = localStorage.getItem(this.localStorageKey);
|
||
|
|
||
|
if (savedScheme == 'light' || savedScheme == 'dark' || savedScheme == 'auto') return savedScheme;
|
||
|
else return 'auto';
|
||
|
}
|
||
|
|
||
|
private bindMatchMedia() {
|
||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||
|
if (e.matches) {
|
||
|
this.systemPreferScheme = 'dark';
|
||
|
}
|
||
|
else {
|
||
|
this.systemPreferScheme = 'light';
|
||
|
}
|
||
|
this.setBodyClass();
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export default StackColorScheme;
|