// Theme management functionality class ThemeManager { constructor() { this.currentTheme = this.getStoredTheme() || this.getPreferredTheme(); this.init(); } init() { this.applyTheme(this.currentTheme); this.setupEventListeners(); } getStoredTheme() { return localStorage.getItem('theme'); } setStoredTheme(theme) { localStorage.setItem('theme', theme); } getPreferredTheme() { if (this.getStoredTheme()) { return this.getStoredTheme(); } return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } applyTheme(theme) { document.body.className = document.body.className.replace(/theme-\w+/, ''); document.body.classList.add(`theme-${theme}`); this.currentTheme = theme; this.setStoredTheme(theme); // Update theme toggle button this.updateThemeToggleButton(); // Dispatch theme change event window.dispatchEvent(new CustomEvent('themeChanged', { detail: { theme: theme } })); } toggleTheme() { const newTheme = this.currentTheme === 'light' ? 'dark' : 'light'; this.applyTheme(newTheme); // Update user preference via API if logged in if (typeof ScriptsManager !== 'undefined') { ScriptsManager.updateUserPreferences({ theme: newTheme }) .catch(error => console.error('Failed to update theme preference:', error)); } } updateThemeToggleButton() { const toggleButton = document.getElementById('theme-toggle'); if (!toggleButton) return; const darkIcon = toggleButton.querySelector('.theme-icon-dark'); const lightIcon = toggleButton.querySelector('.theme-icon-light'); if (this.currentTheme === 'dark') { if (darkIcon) darkIcon.style.display = 'none'; if (lightIcon) lightIcon.style.display = 'inline'; } else { if (darkIcon) darkIcon.style.display = 'inline'; if (lightIcon) lightIcon.style.display = 'none'; } } setupEventListeners() { // Theme toggle button const toggleButton = document.getElementById('theme-toggle'); if (toggleButton) { toggleButton.addEventListener('click', () => this.toggleTheme()); } // Listen for system theme changes window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { if (!this.getStoredTheme()) { this.applyTheme(e.matches ? 'dark' : 'light'); } }); // Listen for custom theme change events window.addEventListener('setTheme', (e) => { this.applyTheme(e.detail.theme); }); } getCurrentTheme() { return this.currentTheme; } setTheme(theme) { if (['light', 'dark'].includes(theme)) { this.applyTheme(theme); } } } // Theme-specific component adjustments class ThemeComponentManager { constructor(themeManager) { this.themeManager = themeManager; this.init(); } init() { // Listen for theme changes window.addEventListener('themeChanged', (e) => { this.adjustComponents(e.detail.theme); }); // Initial adjustment this.adjustComponents(this.themeManager.getCurrentTheme()); } adjustComponents(theme) { this.adjustBootstrapComponents(theme); this.adjustCustomComponents(theme); this.adjustCharts(theme); } adjustBootstrapComponents(theme) { // Adjust modal backdrop const modals = document.querySelectorAll('.modal'); modals.forEach(modal => { if (theme === 'dark') { modal.classList.add('modal-dark'); } else { modal.classList.remove('modal-dark'); } }); // Adjust tooltips const tooltips = document.querySelectorAll('.tooltip'); tooltips.forEach(tooltip => { if (theme === 'dark') { tooltip.classList.add('tooltip-dark'); } else { tooltip.classList.remove('tooltip-dark'); } }); } adjustCustomComponents(theme) { // Adjust log containers const logContainers = document.querySelectorAll('.log-container'); logContainers.forEach(container => { if (theme === 'dark') { container.style.backgroundColor = '#000000'; container.style.color = '#ffffff'; } else { container.style.backgroundColor = '#f8f9fa'; container.style.color = '#212529'; } }); // Adjust code blocks const codeBlocks = document.querySelectorAll('.code-block'); codeBlocks.forEach(block => { if (theme === 'dark') { block.style.backgroundColor = '#2d2d2d'; block.style.color = '#e9ecef'; block.style.borderColor = '#495057'; } else { block.style.backgroundColor = '#f8f9fa'; block.style.color = '#212529'; block.style.borderColor = '#e9ecef'; } }); } adjustCharts(theme) { // Adjust any charts or graphs based on theme // This would be implemented when charts are added const chartContainers = document.querySelectorAll('.chart-container'); chartContainers.forEach(container => { const event = new CustomEvent('themeChanged', { detail: { theme: theme } }); container.dispatchEvent(event); }); } } // Utility functions for theme-aware styling function getThemeAwareColor(lightColor, darkColor) { const theme = window.themeManager ? window.themeManager.getCurrentTheme() : 'light'; return theme === 'dark' ? darkColor : lightColor; } function getThemeAwareCSS(lightCSS, darkCSS) { const theme = window.themeManager ? window.themeManager.getCurrentTheme() : 'light'; return theme === 'dark' ? darkCSS : lightCSS; } // CSS custom properties for theme-aware components function updateThemeCustomProperties(theme) { const root = document.documentElement; if (theme === 'dark') { root.style.setProperty('--theme-bg', '#1a1a1a'); root.style.setProperty('--theme-fg', '#e9ecef'); root.style.setProperty('--theme-border', '#495057'); root.style.setProperty('--theme-muted', '#adb5bd'); root.style.setProperty('--theme-card-bg', '#2d2d2d'); } else { root.style.setProperty('--theme-bg', '#ffffff'); root.style.setProperty('--theme-fg', '#212529'); root.style.setProperty('--theme-border', '#dee2e6'); root.style.setProperty('--theme-muted', '#6c757d'); root.style.setProperty('--theme-card-bg', '#ffffff'); } } // Initialize theme management when DOM is loaded document.addEventListener('DOMContentLoaded', function() { // Create global theme manager instance window.themeManager = new ThemeManager(); window.themeComponentManager = new ThemeComponentManager(window.themeManager); // Update CSS custom properties window.addEventListener('themeChanged', (e) => { updateThemeCustomProperties(e.detail.theme); }); // Initial update updateThemeCustomProperties(window.themeManager.getCurrentTheme()); }); // Export for use in other modules window.ThemeManager = { getThemeAwareColor, getThemeAwareCSS, updateThemeCustomProperties };