Files
personotes/frontend/src/theme-manager.js

212 lines
6.5 KiB
JavaScript

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();
});