// Éditeur de thème : regroupe les couleurs PRINCIPALES de l'app (variables --ops-*) en un seul endroit, // avec presets (défaut indigo actuel + palette de marque Gigafibre extraite de gigafibre.ca), aperçu live et persistance. // But : réduire/uniformiser les couleurs. Chaque token pilote une variable CSS --ops-* (+ miroir Quasar --q-* pour que // les composants Quasar suivent). N.B. les ~2000 hex EN DUR dans les pages ne suivent PAS encore (migration séparée). import { ref } from 'vue' export const THEME_GROUPS = [ { title: 'Marque', hint: "L'accent : boutons, liens, sélections, mises en valeur.", tokens: [ { var: '--ops-accent', label: 'Accent (couleur de marque)', quasar: '--q-primary' }, ] }, { title: 'Sombre', hint: 'Barre latérale + tableau Dispatch.', tokens: [ { var: '--ops-sidebar-bg', label: 'Fond sombre', mirror: '--ops-primary' }, ] }, { title: 'Surfaces', hint: 'Fonds, cartes, bordures.', tokens: [ { var: '--ops-bg', label: 'Fond de page', mirror: '--ops-bg-light' }, { var: '--ops-surface', label: 'Cartes / surfaces' }, { var: '--ops-border', label: 'Bordures' }, { var: '--ops-bg-hover', label: 'Survol / sélection' }, ] }, { title: 'Texte', tokens: [ { var: '--ops-text', label: 'Texte principal' }, { var: '--ops-text-muted', label: 'Texte discret' }, ] }, { title: 'États sémantiques', hint: 'Rôles unifiés (badges, boutons, icônes, notifications) — migrés depuis amber/orange/red/blue.', tokens: [ { var: '--ops-success', label: 'Succès — payé, actif, complété', quasar: '--q-positive' }, { var: '--ops-warning', label: 'Attention — en attente, priorité moyenne', quasar: '--q-warning' }, { var: '--ops-danger', label: 'Erreur — destructif, en retard, urgent', quasar: '--q-negative' }, { var: '--ops-info', label: 'Info — liens externes, en cours', quasar: '--q-info' }, ] }, ] // Palettes. `default` = MODERNE (inspirée des refs zentry/marque : vert + near-black + off-white + teinte verte + gris), // alignée sur css/app.scss. `vif` = vert lime éclatant (#22c11f de la ref — superbe mais texte blanc moins contrasté sur boutons). // `indigo` = ancienne palette (legacy). export const PRESETS = { default: { '--ops-accent': '#16a34a', '--ops-sidebar-bg': '#0d0d0d', '--ops-bg': '#f4f5f2', '--ops-surface': '#ffffff', '--ops-border': '#e5e7e2', '--ops-bg-hover': '#dcf5d3', '--ops-text': '#0d0d0d', '--ops-text-muted': '#6b7280', '--ops-success': '#16a34a', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#2563eb', }, vif: { '--ops-accent': '#22c11f', '--ops-sidebar-bg': '#0d0d0d', '--ops-bg': '#f4f5f2', '--ops-surface': '#ffffff', '--ops-border': '#e5e7e2', '--ops-bg-hover': '#cceecc', '--ops-text': '#0d0d0d', '--ops-text-muted': '#6b7280', '--ops-success': '#16a34a', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#2563eb', }, indigo: { '--ops-accent': '#6366f1', '--ops-sidebar-bg': '#111422', '--ops-bg': '#f8fafc', '--ops-surface': '#ffffff', '--ops-border': '#e2e8f0', '--ops-bg-hover': '#eef2ff', '--ops-text': '#1e293b', '--ops-text-muted': '#64748b', '--ops-success': '#10b981', '--ops-warning': '#f59e0b', '--ops-danger': '#ef4444', '--ops-info': '#3b82f6', }, } const KEY = 'ops_theme_v1' export const themeVars = ref({}) export function allTokens () { return THEME_GROUPS.flatMap(g => g.tokens) } // Applique un jeu de couleurs en direct : pose les variables --ops-* (+ miroirs Quasar/alias) sur :root. export function applyTheme (vars) { const root = document.documentElement for (const t of allTokens()) { const v = vars[t.var]; if (!v) continue root.style.setProperty(t.var, v) if (t.mirror) root.style.setProperty(t.mirror, v) if (t.quasar) root.style.setProperty(t.quasar, v) } themeVars.value = { ...vars } } // Valeurs effectives courantes (override appliqué OU valeur CSS calculée OU défaut). export function currentValues () { const cs = getComputedStyle(document.documentElement); const out = {} for (const t of allTokens()) out[t.var] = (themeVars.value[t.var] || cs.getPropertyValue(t.var).trim() || PRESETS.default[t.var]) return out } export function saveTheme (vars) { try { localStorage.setItem(KEY, JSON.stringify(vars)) } catch (e) {} applyTheme(vars) } export function resetTheme () { try { localStorage.removeItem(KEY) } catch (e) {} applyTheme(PRESETS.default) } export function loadSavedTheme () { try { const s = localStorage.getItem(KEY); if (s) applyTheme(JSON.parse(s)) } catch (e) {} }