import { defineStore } from 'pinia'
import { ref } from 'vue'
// Theme classification -- matches React themes/index.ts
export const DARK_THEMES = ['dark', 'darkNeu', 'darkoBluo', 'matrix']
export const LIGHT_THEMES = ['light', 'enterprise', 'redis']
export const ALL_THEME_KEYS = ['light', 'enterprise', 'dark', 'darkNeu', 'darkoBluo', 'matrix', 'redis']
export function isDarkTheme(key: string): boolean {
return DARK_THEMES.includes(key)
}
const STORAGE_KEY = 'p3xr-theme'
const AUTO = 'auto'
function getSystemDark(): boolean {
return typeof window !== 'undefined' && window.matchMedia?.('(prefers-color-scheme: dark)').matches
}
function normalizeThemeKey(raw: string): string {
// Handle Angular format: p3xrThemeDark -> dark, p3xrThemeEnterprise -> enterprise
if (raw.startsWith('p3xrTheme')) {
const name = raw.replace('p3xrTheme', '')
return name.charAt(0).toLowerCase() + name.slice(1)
}
return raw
}
function readStored(): string {
try {
const raw = localStorage.getItem(STORAGE_KEY) || AUTO
if (raw === AUTO) return AUTO
return normalizeThemeKey(raw)
} catch { return AUTO }
}
function applyBodyClasses(resolved: string): void {
if (typeof document === 'undefined') return
const dark = isDarkTheme(resolved)
const scheme = dark ? 'dark' : 'light'
document.documentElement.setAttribute('data-color-scheme', scheme)
document.documentElement.style.colorScheme = scheme
document.body.style.colorScheme = scheme
document.body.classList.toggle('p3xr-theme-dark', dark)
document.body.classList.toggle('p3xr-theme-light', !dark)
// Update the <meta name="color-scheme"> tag set in index.html
const meta = document.querySelector('meta[name="color-scheme"]') as HTMLMetaElement
if (meta) meta.content = scheme
}
// Same logic as Angular ThemeService
function resolveThemeKey(stored: string): string {
if (stored === AUTO) return getSystemDark() ? 'dark' : 'enterprise'
return stored
}
export const useThemeStore = defineStore('theme', () => {
const stored = readStored()
const isAuto = ref(stored === AUTO)
const themeKey = ref(resolveThemeKey(stored))
const storedValue = ref(stored)
// Apply on initial load
applyBodyClasses(themeKey.value)
function setTheme(choice: string) {
const auto = choice === AUTO
const resolved = auto ? resolveThemeKey(AUTO) : choice
try { localStorage.setItem(STORAGE_KEY, choice) } catch {}
applyBodyClasses(resolved)
// Notify Electron parent
try {
window.parent?.postMessage({ type: 'p3x-theme-change', dark: isDarkTheme(resolved) }, '*')
} catch {}
isAuto.value = auto
themeKey.value = resolved
storedValue.value = choice
}
// Listen for system theme changes (auto mode)
if (typeof window !== 'undefined' && window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
if (isAuto.value) {
const resolved = getSystemDark() ? 'dark' : 'enterprise'
applyBodyClasses(resolved)
themeKey.value = resolved
}
})
}
return {
isAuto,
themeKey,
storedValue,
setTheme,
}
})