Core/ThemeEngine.ps1
|
# Core\ThemeEngine.ps1 # Centralized theme definitions and CSS export function Get-PoshThemes { <# .SYNOPSIS List all available PoshDE themes. #> [CmdletBinding()] param() @( [PSCustomObject]@{ Name = 'samurai'; Description = 'Red/magenta with cyan accents — default' } [PSCustomObject]@{ Name = 'cyberpunk'; Description = 'Yellow/cyan — Cyberpunk 2077 inspired' } [PSCustomObject]@{ Name = 'matrix'; Description = 'Classic green on black' } [PSCustomObject]@{ Name = 'midnight'; Description = 'Deep blue with purple accents' } [PSCustomObject]@{ Name = 'hacker'; Description = 'Green/amber old-school terminal' } [PSCustomObject]@{ Name = 'default'; Description = 'Clean modern dark' } ) } function Get-PoshTheme { <# .SYNOPSIS Get a theme object by name, or the currently active theme. .PARAMETER Name Theme name. If omitted, returns the active theme. .EXAMPLE $theme = Get-PoshTheme $theme.colors.primary .EXAMPLE $theme = Get-PoshTheme -Name matrix #> [CmdletBinding()] param( [string]$Name ) if (-not $Name) { $Name = $script:PoshDE.CurrentTheme } $theme = switch ($Name.ToLower()) { 'samurai' { @{ name = 'samurai' description = 'Red/magenta with cyan accents' colors = @{ primary = '#ff0064' secondary = '#00ffff' accent = '#ff6464' warning = '#ffc800' success = '#00ff64' error = '#ff3232' bgDark = '#0a0a0a' bgMedium = '#141414' bgLight = '#1e1e1e' bgOverlay = 'rgba(0,0,0,0.85)' textPrimary = 'rgba(255,255,255,0.9)' textSecondary = 'rgba(255,255,255,0.6)' textMuted = 'rgba(255,255,255,0.4)' border = 'rgba(255,0,100,0.3)' glow = 'rgba(255,0,100,0.5)' glowSecondary = 'rgba(0,255,255,0.5)' } fonts = @{ primary = "'Consolas', 'Courier New', monospace" display = "'Segoe UI', sans-serif" mono = "'Cascadia Code', 'Consolas', monospace" sizes = @{ xs = '9px'; sm = '11px'; md = '13px'; lg = '16px'; xl = '20px' } } effects = @{ glowStrength = '10px'; borderRadius = '3px'; transitionSpeed = '0.2s' } } } 'cyberpunk' { @{ name = 'cyberpunk' description = 'Yellow/cyan — Cyberpunk 2077 inspired' colors = @{ primary = '#fcee0a' secondary = '#00ffff' accent = '#ff00ff' warning = '#ff6600' success = '#00ff00' error = '#ff0000' bgDark = '#0d0d0d' bgMedium = '#1a1a1a' bgLight = '#2a2a2a' bgOverlay = 'rgba(0,0,0,0.9)' textPrimary = 'rgba(255,255,255,0.95)' textSecondary = 'rgba(252,238,10,0.8)' textMuted = 'rgba(255,255,255,0.5)' border = 'rgba(252,238,10,0.4)' glow = 'rgba(252,238,10,0.6)' glowSecondary = 'rgba(0,255,255,0.5)' } fonts = @{ primary = "'Consolas', monospace" display = "'Rajdhani', 'Segoe UI', sans-serif" mono = "'Cascadia Code', monospace" sizes = @{ xs = '9px'; sm = '11px'; md = '13px'; lg = '16px'; xl = '20px' } } effects = @{ glowStrength = '15px'; borderRadius = '0px'; transitionSpeed = '0.15s' } } } 'matrix' { @{ name = 'matrix' description = 'Classic green on black' colors = @{ primary = '#00ff00' secondary = '#00cc00' accent = '#00ff66' warning = '#ffff00' success = '#00ff00' error = '#ff0000' bgDark = '#000000' bgMedium = '#0a0a0a' bgLight = '#141414' bgOverlay = 'rgba(0,0,0,0.95)' textPrimary = '#00ff00' textSecondary = '#00cc00' textMuted = '#006600' border = 'rgba(0,255,0,0.3)' glow = 'rgba(0,255,0,0.5)' glowSecondary = 'rgba(0,255,0,0.3)' } fonts = @{ primary = "'Courier New', monospace" display = "'Courier New', monospace" mono = "'Courier New', monospace" sizes = @{ xs = '10px'; sm = '12px'; md = '14px'; lg = '16px'; xl = '20px' } } effects = @{ glowStrength = '8px'; borderRadius = '0px'; transitionSpeed = '0.1s' } } } 'midnight' { @{ name = 'midnight' description = 'Deep blue with purple accents' colors = @{ primary = '#6366f1' secondary = '#a855f7' accent = '#ec4899' warning = '#f59e0b' success = '#10b981' error = '#ef4444' bgDark = '#0f0f1a' bgMedium = '#1a1a2e' bgLight = '#252542' bgOverlay = 'rgba(15,15,26,0.95)' textPrimary = 'rgba(255,255,255,0.9)' textSecondary = 'rgba(255,255,255,0.6)' textMuted = 'rgba(255,255,255,0.4)' border = 'rgba(99,102,241,0.3)' glow = 'rgba(99,102,241,0.5)' glowSecondary = 'rgba(168,85,247,0.5)' } fonts = @{ primary = "'Inter', 'Segoe UI', sans-serif" display = "'Inter', sans-serif" mono = "'JetBrains Mono', 'Cascadia Code', monospace" sizes = @{ xs = '10px'; sm = '12px'; md = '14px'; lg = '16px'; xl = '20px' } } effects = @{ glowStrength = '12px'; borderRadius = '6px'; transitionSpeed = '0.2s' } } } 'hacker' { @{ name = 'hacker' description = 'Green/amber old-school terminal' colors = @{ primary = '#33ff33' secondary = '#ffb000' accent = '#ff6600' warning = '#ffb000' success = '#33ff33' error = '#ff3333' bgDark = '#0a0a00' bgMedium = '#0d0d00' bgLight = '#1a1a00' bgOverlay = 'rgba(10,10,0,0.95)' textPrimary = '#33ff33' textSecondary = '#ffb000' textMuted = '#666633' border = 'rgba(51,255,51,0.3)' glow = 'rgba(51,255,51,0.4)' glowSecondary = 'rgba(255,176,0,0.4)' } fonts = @{ primary = "'VT323', 'Courier New', monospace" display = "'VT323', monospace" mono = "'VT323', 'Courier New', monospace" sizes = @{ xs = '12px'; sm = '14px'; md = '16px'; lg = '18px'; xl = '24px' } } effects = @{ glowStrength = '6px'; borderRadius = '0px'; transitionSpeed = '0.05s' } } } default { @{ name = 'default' description = 'Clean modern dark' colors = @{ primary = '#0078d4' secondary = '#00b4d8' accent = '#48cae4' warning = '#ffc107' success = '#28a745' error = '#dc3545' bgDark = '#1e1e1e' bgMedium = '#252526' bgLight = '#333333' bgOverlay = 'rgba(30,30,30,0.95)' textPrimary = '#ffffff' textSecondary = '#cccccc' textMuted = '#888888' border = 'rgba(255,255,255,0.1)' glow = 'rgba(0,120,212,0.5)' glowSecondary = 'rgba(0,180,216,0.5)' } fonts = @{ primary = "'Segoe UI', sans-serif" display = "'Segoe UI', sans-serif" mono = "'Cascadia Code', 'Consolas', monospace" sizes = @{ xs = '10px'; sm = '12px'; md = '14px'; lg = '16px'; xl = '20px' } } effects = @{ glowStrength = '5px'; borderRadius = '4px'; transitionSpeed = '0.2s' } } } } [PSCustomObject]$theme } function Set-PoshTheme { <# .SYNOPSIS Set the active theme for all Posh apps. .DESCRIPTION Persists the selection to config.json. Apps pick up the new theme next time they call Get-PoshTheme or Export-PoshThemeCSS. .PARAMETER Name Theme name. .EXAMPLE Set-PoshTheme -Name matrix #> [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet('samurai','cyberpunk','matrix','midnight','hacker','default')] [string]$Name ) $script:PoshDE.CurrentTheme = $Name $configPath = Join-Path $script:PoshDE.AppDataPath "config.json" @{ CurrentTheme = $Name } | ConvertTo-Json | Set-Content -Path $configPath -Encoding UTF8 Write-Host "Theme set to '" -NoNewline -ForegroundColor DarkGray Write-Host $Name -NoNewline -ForegroundColor Cyan Write-Host "'. Restart apps to apply." -ForegroundColor DarkGray } function Export-PoshThemeCSS { <# .SYNOPSIS Export the active theme (or a named theme) as a CSS :root block. .DESCRIPTION Posh apps inject this into their WebView2 frontend via /api/theme. .PARAMETER Name Theme name. Defaults to active theme. .EXAMPLE $css = Export-PoshThemeCSS .EXAMPLE $css = Export-PoshThemeCSS -Name cyberpunk #> [CmdletBinding()] param( [string]$Name ) $t = Get-PoshTheme -Name $Name @" :root { --color-primary: $($t.colors.primary); --color-secondary: $($t.colors.secondary); --color-accent: $($t.colors.accent); --color-warning: $($t.colors.warning); --color-success: $($t.colors.success); --color-error: $($t.colors.error); --bg-dark: $($t.colors.bgDark); --bg-medium: $($t.colors.bgMedium); --bg-light: $($t.colors.bgLight); --bg-overlay: $($t.colors.bgOverlay); --text-primary: $($t.colors.textPrimary); --text-secondary: $($t.colors.textSecondary); --text-muted: $($t.colors.textMuted); --border-color: $($t.colors.border); --glow-color: $($t.colors.glow); --glow-secondary: $($t.colors.glowSecondary); --glow-strength: $($t.effects.glowStrength); --border-radius: $($t.effects.borderRadius); --transition-speed: $($t.effects.transitionSpeed); --font-primary: $($t.fonts.primary); --font-display: $($t.fonts.display); --font-mono: $($t.fonts.mono); --font-size-xs: $($t.fonts.sizes.xs); --font-size-sm: $($t.fonts.sizes.sm); --font-size-md: $($t.fonts.sizes.md); --font-size-lg: $($t.fonts.sizes.lg); --font-size-xl: $($t.fonts.sizes.xl); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(--font-primary); font-size: var(--font-size-md); color: var(--text-primary); background: var(--bg-dark); } "@ } Write-Verbose "ThemeEngine loaded" |