import { i18n, t } from '../i18n.js'; import { router } from '../router.js'; class AppHeader extends HTMLElement { constructor() { super(); this.langDropdownOpen = false; this.handleOutsideClick = this.handleOutsideClick.bind(this); this.handleKeydown = this.handleKeydown.bind(this); } connectedCallback() { this.render(); this.setupEventListeners(); document.addEventListener('click', this.handleOutsideClick); document.addEventListener('keydown', this.handleKeydown); } disconnectedCallback() { document.removeEventListener('click', this.handleOutsideClick); document.removeEventListener('keydown', this.handleKeydown); } handleOutsideClick() { if (this.langDropdownOpen) { this.closeDropdown(); } } handleKeydown(e) { if (!this.langDropdownOpen) return; const items = Array.from(this.querySelectorAll('.dropdown-item')); const currentIndex = items.findIndex(item => item === document.activeElement); switch (e.key) { case 'Escape': e.preventDefault(); this.closeDropdown(); this.querySelector('#lang-toggle')?.focus(); break; case 'ArrowDown': e.preventDefault(); const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0; items[nextIndex]?.focus(); break; case 'ArrowUp': e.preventDefault(); const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1; items[prevIndex]?.focus(); break; } } closeDropdown() { this.langDropdownOpen = false; const langDropdown = this.querySelector('#lang-dropdown'); const langToggle = this.querySelector('#lang-toggle'); langDropdown?.classList.remove('open'); langToggle?.setAttribute('aria-expanded', 'false'); } openDropdown() { this.langDropdownOpen = true; const langDropdown = this.querySelector('#lang-dropdown'); const langToggle = this.querySelector('#lang-toggle'); langDropdown?.classList.add('open'); langToggle?.setAttribute('aria-expanded', 'true'); this.querySelector('.dropdown-item.active')?.focus(); } render() { this.innerHTML = /* html */`
`; } setupEventListeners() { const themeToggle = this.querySelector('#theme-toggle'); themeToggle.addEventListener('click', () => this.toggleTheme()); const langDropdown = this.querySelector('#lang-dropdown'); const langToggle = this.querySelector('#lang-toggle'); langToggle.addEventListener('click', (e) => { e.stopPropagation(); if (this.langDropdownOpen) { this.closeDropdown(); } else { this.openDropdown(); } }); langDropdown.querySelectorAll('[data-locale]').forEach(btn => { btn.addEventListener('click', async () => { await i18n.setLocale(btn.dataset.locale); this.closeDropdown(); this.render(); this.setupEventListeners(); }); }); this.updateThemeIcon(); } toggleTheme() { const currentTheme = document.documentElement.dataset.theme; const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; let newTheme; if (!currentTheme) { newTheme = prefersDark ? 'light' : 'dark'; } else if (currentTheme === 'dark') { newTheme = 'light'; } else { newTheme = 'dark'; } document.documentElement.dataset.theme = newTheme; localStorage.setItem('theme', newTheme); this.updateThemeIcon(); } updateThemeIcon() { const theme = document.documentElement.dataset.theme; const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const isDark = theme === 'dark' || (!theme && prefersDark); const sunIcon = this.querySelector('.icon-sun'); const moonIcon = this.querySelector('.icon-moon'); if (sunIcon && moonIcon) { sunIcon.style.display = isDark ? 'block' : 'none'; moonIcon.style.display = isDark ? 'none' : 'block'; } } updateTranslations() { i18n.updateDOM(); this.querySelector('#current-lang').textContent = i18n.getLocale().toUpperCase(); } } customElements.define('app-header', AppHeader);