feat: globale icon-kleuring via .lucide-<name> CSS-injectie

This commit is contained in:
mo
2026-07-21 22:26:19 +02:00
parent 345bc84640
commit 2e0284f372
5 changed files with 213 additions and 144 deletions
+99 -32
View File
@@ -1,45 +1,113 @@
import { createContext, useContext, useEffect, useState } from 'react';
import { api } from './api';
// Legacy standaard-icoonkleuren (fallback als gebruiker ze niet zelf heeft ingesteld)
const DEFAULT_ICON_COLORS = {
'layout-dashboard': '#58a6ff', 'users': '#3fb950', 'briefcase': '#d29922',
'server': '#bc8cff', 'check-circle': '#3fb950', 'lightbulb': '#d29922',
'clock': '#79c0ff', 'eye': '#f778ba', 'phone': '#3fb950', 'file-text': '#f778ba',
'edit-3': '#79c0ff', 'folder': '#d29922', 'clipboard-list': '#bc8cff',
'mail': '#58a6ff', 'calendar': '#79c0ff', 'receipt': '#d29922', 'wallet': '#3fb950',
'bar-chart-3': '#bc8cff', 'share-2': '#58a6ff', 'network': '#00d4ff', 'radar': '#d29922',
'sparkles': '#bc8cff', 'settings': '#8b9bb8', 'shield-check': '#3fb950',
'pen-tool': '#bc8cff', 'file-search': '#d29922', 'folder-kanban': '#d29922', 'cpu': '#58a6ff',
'building-2': '#bc8cff', 'activity': '#58a6ff', 'search': '#8b9bb8', 'bell': '#d29922',
'plus': '#00d4ff', 'trash-2': '#f85149', 'pencil': '#79c0ff', 'star': '#d29922',
'map-pin': '#58a6ff', 'globe': '#58a6ff', 'send': '#00d4ff', 'download': '#79c0ff',
'upload': '#79c0ff', 'save': '#3fb950', 'refresh-cw': '#58a6ff', 'filter': '#8b9bb8',
'more-vertical': '#8b9bb8', 'x': '#8b9bb8', 'menu': '#8b9bb8', 'external-link': '#8b9bb8',
'log-out': '#8b9bb8', 'trending-up': '#3fb950', 'pie-chart': '#bc8cff', 'target': '#d29922',
'shield': '#3fb950', 'zap': '#bc8cff', 'database': '#58a6ff', 'cloud': '#79c0ff',
'hard-drive': '#bc8cff', 'monitor': '#58a6ff', 'git-branch': '#f778ba', 'package': '#d29922',
'terminal': '#79c0ff', 'code': '#58a6ff', 'layers': '#bc8cff', 'link': '#58a6ff',
'unlink': '#8b9bb8', 'copy': '#79c0ff', 'check': '#3fb950', 'alert-triangle': '#d29922',
'info': '#58a6ff', 'help-circle': '#8b9bb8', 'type': '#79c0ff', 'columns': '#bc8cff',
'table': '#58a6ff', 'list': '#79c0ff', 'grid': '#bc8cff', 'tag': '#d29922',
'calendar-days': '#79c0ff', 'mail-open': '#58a6ff', 'inbox': '#58a6ff', 'send-horizontal': '#00d4ff',
'paperclip': '#8b9bb8', 'users-round': '#3fb950', 'projector': '#bc8cff', 'kanban-square': '#d29922',
'bar-chart': '#bc8cff', 'line-chart': '#58a6ff', 'activity-square': '#3fb950',
'server': '#bc8cff', 'wifi': '#58a6ff', 'ethernet-port': '#58a6ff', 'router': '#bc8cff',
'switch': '#3fb950', 'firewall': '#f85149', 'storage': '#bc8cff', 'ups': '#d29922',
'pdu': '#79c0ff', 'cloud-upload': '#58a6ff', 'cloud-download': '#58a6ff',
'brain-circuit': '#bc8cff', 'message-square': '#58a6ff', 'bot': '#bc8cff',
'key': '#f778ba', 'shield-check-big': '#3fb950', 'lock': '#79c0ff', 'unlock': '#8b9bb8'
// Legacy standaard-icoonkleuren (alle Lucide-iconen op de pagina een unieke kleur)
export const DEFAULT_ICON_COLORS = {
// Navigation & Core Domains
'layout-dashboard': '#58a6ff',
'users': '#3fb950',
'briefcase': '#d29922',
'check-circle': '#3fb950',
'check-circle-2': '#3fb950',
'check-square': '#3fb950',
'check-check': '#3fb950',
'calendar': '#79c0ff',
'mail': '#58a6ff',
'mail-plus': '#58a6ff',
'inbox': '#58a6ff',
'folder-kanban': '#d29922',
'clock': '#79c0ff',
'receipt': '#d29922',
'wallet': '#3fb950',
'bar-chart-3': '#bc8cff',
'bar-chart': '#bc8cff',
'server': '#bc8cff',
'share-2': '#58a6ff',
'network': '#00d4ff',
'radar': '#d29922',
'sparkles': '#bc8cff',
'settings': '#8b9bb8',
// Legacy & Platform
'shield-check': '#3fb950',
'pen-tool': '#bc8cff',
'file-search': '#d29922',
// Actions & Tools
'plus': '#00d4ff',
'pencil': '#79c0ff',
'trash-2': '#f85149',
'trash': '#f85149',
'search': '#8b9bb8',
'search-x': '#f85149',
'refresh-cw': '#58a6ff',
'download': '#79c0ff',
'upload': '#79c0ff',
'database-backup': '#bc8cff',
'send': '#00d4ff',
'star': '#d29922',
'bot': '#bc8cff',
'filter': '#8b9bb8',
// Infra & Entities
'building-2': '#bc8cff',
'factory': '#bc8cff',
'map-pin': '#58a6ff',
'cable': '#58a6ff',
'workflow': '#bc8cff',
// Status & Info
'bell': '#d29922',
'file-text': '#f778ba',
'lightbulb': '#d29922',
'alert-triangle': '#f85149',
'activity': '#58a6ff',
'construction': '#d29922',
'flag': '#f85149',
'user': '#3fb950',
'euro': '#3fb950',
'external-link': '#8b9bb8',
'log-out': '#f85149',
'menu': '#8b9bb8',
'x': '#8b9bb8'
};
// Injecteert globale CSS-regels voor alle .lucide-<name> elementen op de pagina
export function injectIconStyles(customColors) {
let styleEl = document.getElementById('mek-icon-colors');
if (!styleEl) {
styleEl = document.createElement('style');
styleEl.id = 'mek-icon-colors';
document.head.appendChild(styleEl);
}
const merged = { ...DEFAULT_ICON_COLORS, ...(customColors || {}) };
let css = '/* Dynamic Icon Colors */\n';
for (const [name, color] of Object.entries(merged)) {
if (!color) continue;
css += `.lucide-${name}, [data-lucide="${name}"] { color: ${color}; }\n`;
}
styleEl.textContent = css;
}
const SettingsContext = createContext({ settings: null, loading: true });
export function SettingsProvider({ children }) {
const [settings, setSettings] = useState(null);
useEffect(() => {
api.get('/settings').then(setSettings).catch(() => setSettings(null));
// Injecteer meteen de standaardkleuren voor snelle weergave
injectIconStyles(null);
api.get('/settings')
.then(s => {
setSettings(s);
if (s?.icon_colors) {
injectIconStyles(s.icon_colors);
}
})
.catch(() => setSettings(null));
}, []);
return (
<SettingsContext.Provider value={{ settings, loading: !settings }}>
{children}
@@ -51,7 +119,6 @@ export function useSettings() {
return useContext(SettingsContext);
}
// Geef de kleur voor een icoon terug (user-instelling of legacy default)
export function iconColor(name, settings) {
if (settings?.icon_colors && settings.icon_colors[name]) return settings.icon_colors[name];
return DEFAULT_ICON_COLORS[name] || null;