use std::fmt::Display;
use palette::{IntoColor, Oklch, Srgb};
use serde::{Deserialize, Serialize};
use crate::theme::{Color, ThemeType};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Theme {
pub primary: Color,
pub secondary: Color,
pub background: Color,
pub surface: Color,
pub border: Color,
pub foreground: Color,
pub muted: Color,
pub success: Color,
pub warning: Color,
pub error: Color,
}
impl Theme {
pub fn generate(theme_type: ThemeType, rgb: (u8, u8, u8)) -> Self {
match theme_type {
ThemeType::Dark => Self::dark(rgb),
ThemeType::Light => Self::light(rgb),
}
}
pub fn dark((r, g, b): (u8, u8, u8)) -> Self {
let color: Oklch =
Srgb::new(r as f32 / 255., g as f32 / 255., b as f32 / 255.)
.into_color();
let (secondary, success, warning, error) = Self::shared_colors(color);
Self {
primary: Color(color),
secondary: Color(secondary),
background: Color(Oklch::new(0.20, 0.006, color.hue)),
surface: Color(Oklch::new(0.25, 0.008, color.hue)),
border: Color(Oklch::new(0.32, 0.010, color.hue)),
foreground: Color(Oklch::new(0.9, 0.01, color.hue)),
muted: Color(Oklch::new(0.65, 0.02, color.hue)),
success: Color(success),
warning: Color(warning),
error: Color(error),
}
}
pub fn light((r, g, b): (u8, u8, u8)) -> Self {
let mut color: Oklch =
Srgb::new(r as f32 / 255., g as f32 / 255., b as f32 / 255.)
.into_color();
color.l = color.l.min(0.70);
let (secondary, success, warning, error) = Self::shared_colors(color);
Self {
primary: Color(color),
secondary: Color(secondary),
background: Color(Oklch::new(0.98, 0.004, color.hue)),
surface: Color(Oklch::new(0.94, 0.006, color.hue)),
border: Color(Oklch::new(0.85, 0.010, color.hue)),
foreground: Color(Oklch::new(0.15, 0.01, color.hue)),
muted: Color(Oklch::new(0.45, 0.02, color.hue)),
success: Color(success),
warning: Color(warning),
error: Color(error),
}
}
fn shared_colors(color: Oklch) -> (Oklch, Oklch, Oklch, Oklch) {
let mut secondary = color;
secondary.hue += 35.;
let mut success = color;
success.hue = 140.0.into();
let mut warning = color;
warning.hue = 100.0.into();
let mut error = color;
error.hue = 25.0.into();
(secondary, success, warning, error)
}
}
impl Display for Theme {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Primary: {} \x1b[0m", self.primary)?;
writeln!(f, "Secondary: {} \x1b[0m", self.secondary)?;
writeln!(f, "Background: {} \x1b[0m", self.background)?;
writeln!(f, "Surface: {} \x1b[0m", self.surface)?;
writeln!(f, "Border: {} \x1b[0m", self.border)?;
writeln!(f, "Foreground: {} \x1b[0m", self.foreground)?;
writeln!(f, "Muted: {} \x1b[0m", self.muted)?;
writeln!(f, "Success: {} \x1b[0m", self.success)?;
writeln!(f, "Warning: {} \x1b[0m", self.warning)?;
write!(f, "Error: {} \x1b[0m", self.error)
}
}