import { debug, debugError } from './debug.js'; /** * ThemeManager - Gère le système de thèmes de l'application * Permet de changer entre différents thèmes et persiste le choix dans localStorage */ class ThemeManager { constructor() { this.themes = [ { id: 'material-dark', name: 'Material Dark', icon: '🌙', description: 'Thème professionnel inspiré de Material Design' }, { id: 'monokai-dark', name: 'Monokai Dark', icon: '🎨', description: 'Palette Monokai classique pour les développeurs' }, { id: 'dracula', name: 'Dracula', icon: '🧛', description: 'Thème sombre élégant avec des accents violets et cyan' }, { id: 'one-dark', name: 'One Dark', icon: '⚡', description: 'Thème populaire d\'Atom avec des couleurs douces' }, { id: 'solarized-dark', name: 'Solarized Dark', icon: '☀️', description: 'Palette scientifiquement optimisée pour réduire la fatigue oculaire' }, { id: 'nord', name: 'Nord', icon: '❄️', description: 'Palette arctique apaisante avec des tons bleus froids' }, { id: 'catppuccin', name: 'Catppuccin', icon: '🌸', description: 'Thème pastel doux et chaleureux avec des accents roses et bleus' }, { id: 'everforest', name: 'Everforest', icon: '🌲', description: 'Palette naturelle inspirée de la forêt avec des tons verts et beiges' } ]; this.currentTheme = this.loadTheme(); this.init(); } init() { // Appliquer le thème sauvegardé this.applyTheme(this.currentTheme); // Écouter les événements HTMX pour réinitialiser les listeners document.body.addEventListener('htmx:afterSwap', (event) => { if (event.detail.target.id === 'sidebar' || event.detail.target.closest('#sidebar')) { this.attachModalListeners(); } }); debug('ThemeManager initialized with theme:', this.currentTheme); } loadTheme() { // Charger le thème depuis localStorage, par défaut 'material-dark' return localStorage.getItem('app-theme') || 'material-dark'; } saveTheme(themeId) { localStorage.setItem('app-theme', themeId); } applyTheme(themeId) { // Appliquer le thème sur l'élément racine document.documentElement.setAttribute('data-theme', themeId); this.currentTheme = themeId; this.saveTheme(themeId); // Mettre à jour les cartes de thème si la modale est ouverte this.updateThemeCards(); debug('Theme applied:', themeId); } openThemeModal() { const modal = document.getElementById('theme-modal'); if (modal) { modal.style.display = 'flex'; this.updateThemeCards(); } } closeThemeModal() { const modal = document.getElementById('theme-modal'); if (modal) { modal.style.display = 'none'; } } updateThemeCards() { // Mettre à jour l'état actif des cartes de thème const cards = document.querySelectorAll('.theme-card'); cards.forEach(card => { const themeId = card.dataset.theme; if (themeId === this.currentTheme) { card.classList.add('active'); } else { card.classList.remove('active'); } }); } attachModalListeners() { // Ré-attacher les listeners après un swap HTMX const settingsBtn = document.getElementById('theme-settings-btn'); if (settingsBtn) { settingsBtn.replaceWith(settingsBtn.cloneNode(true)); const newBtn = document.getElementById('theme-settings-btn'); newBtn.addEventListener('click', () => this.openThemeModal()); } } getThemes() { return this.themes; } getCurrentTheme() { return this.currentTheme; } } /** * Fonctions globales pour les boutons */ window.openThemeModal = function() { if (window.themeManager) { window.themeManager.openThemeModal(); } }; window.closeThemeModal = function() { if (window.themeManager) { window.themeManager.closeThemeModal(); } }; window.selectTheme = function(themeId) { if (window.themeManager) { window.themeManager.applyTheme(themeId); } }; window.switchSettingsTab = function(tabName) { debug('Switching to tab:', tabName); // Désactiver tous les onglets const tabs = document.querySelectorAll('.settings-tab'); tabs.forEach(tab => tab.classList.remove('active')); // Cacher toutes les sections document.getElementById('themes-section').style.display = 'none'; document.getElementById('fonts-section').style.display = 'none'; document.getElementById('editor-section').style.display = 'none'; const otherSection = document.getElementById('other-section'); if (otherSection) { otherSection.style.display = 'none'; } // Activer l'onglet cliqué const activeTab = Array.from(tabs).find(tab => { const text = tab.textContent.toLowerCase(); if (tabName === 'themes') return text.includes('thème'); if (tabName === 'fonts') return text.includes('police'); if (tabName === 'editor') return text.includes('éditeur'); if (tabName === 'other') return text.includes('autre'); return false; }); if (activeTab) { activeTab.classList.add('active'); } // Afficher la section correspondante const sectionId = tabName + '-section'; const section = document.getElementById(sectionId); if (section) { section.style.display = 'block'; debug('Showing section:', sectionId); } else { console.error('Section not found:', sectionId); } }; /** * Initialisation automatique */ document.addEventListener('DOMContentLoaded', () => { window.themeManager = new ThemeManager(); });