|
/**
|
|
* @fileoverview Theme Selector Component for Rantii
|
|
* @author retoor <retoor@molodetz.nl>
|
|
* @description UI for selecting application color themes
|
|
* @keywords theme, selector, dark, light, appearance
|
|
*/
|
|
|
|
import { BaseComponent } from './base-component.js';
|
|
import { THEMES } from '../services/theme.js';
|
|
|
|
class ThemeSelector extends BaseComponent {
|
|
init() {
|
|
this.themeChangeHandler = () => this.render();
|
|
this.render();
|
|
this.bindEvents();
|
|
}
|
|
|
|
render() {
|
|
const currentTheme = this.getTheme()?.getTheme() || 'dark';
|
|
const themes = Object.entries(THEMES);
|
|
|
|
this.setHtml(`
|
|
<div class="theme-selector">
|
|
<label class="theme-label">Theme</label>
|
|
<div class="theme-options">
|
|
${themes.map(([key, theme]) => `
|
|
<button class="theme-option ${key === currentTheme ? 'active' : ''}"
|
|
data-theme="${key}"
|
|
aria-pressed="${key === currentTheme}">
|
|
<span class="theme-preview theme-preview-${key}"></span>
|
|
<span class="theme-name">${theme.name}</span>
|
|
</button>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
`);
|
|
}
|
|
|
|
bindEvents() {
|
|
this.on(this, 'click', this.handleClick);
|
|
window.addEventListener('rantii:theme-change', this.themeChangeHandler);
|
|
}
|
|
|
|
onDisconnected() {
|
|
window.removeEventListener('rantii:theme-change', this.themeChangeHandler);
|
|
}
|
|
|
|
handleClick(e) {
|
|
const option = e.target.closest('.theme-option');
|
|
if (!option) return;
|
|
|
|
const theme = option.dataset.theme;
|
|
if (theme) {
|
|
this.getTheme()?.setTheme(theme);
|
|
this.render();
|
|
}
|
|
}
|
|
}
|
|
|
|
customElements.define('theme-selector', ThemeSelector);
|
|
|
|
export { ThemeSelector };
|