#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Color {
Rgb(u8, u8, u8),
Ansi256(u8),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorMode {
Auto,
TrueColor,
Ansi256,
NoColor,
}
#[derive(Clone, Debug)]
pub struct Palette {
colors: Vec<Color>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Preset {
NeonCyber,
ArcticTech,
SunsetNeon,
ForestSky,
Chrome,
CrtAmber,
OceanFlow,
DeepSpace,
FireWarning,
WarmLuxury,
EarthTone,
RoyalPurple,
Matrix,
AuroraFlux,
}
impl Palette {
pub fn new(colors: Vec<Color>) -> Self {
Self { colors }
}
pub fn from_hex(hexes: &[&str]) -> Self {
let mut colors = Vec::with_capacity(hexes.len());
for hex in hexes {
if let Some(color) = parse_hex_color(hex) {
colors.push(color);
}
}
Self { colors }
}
pub fn preset(preset: Preset) -> Self {
Self::from_hex(preset.hexes())
}
pub fn colors(&self) -> &[Color] {
&self.colors
}
}
impl Color {
pub fn lerp(self, other: Color, t: f32) -> Color {
match (self, other) {
(Color::Rgb(r1, g1, b1), Color::Rgb(r2, g2, b2)) => {
let t = t.clamp(0.0, 1.0);
let r = (r1 as f32 + (r2 as f32 - r1 as f32) * t).round() as u8;
let g = (g1 as f32 + (g2 as f32 - g1 as f32) * t).round() as u8;
let b = (b1 as f32 + (b2 as f32 - b1 as f32) * t).round() as u8;
Color::Rgb(r, g, b)
}
(left, _) => left,
}
}
}
fn parse_hex_color(input: &str) -> Option<Color> {
let hex = input.trim().trim_start_matches('#');
if hex.len() != 6 {
return None;
}
let r = u8::from_str_radix(&hex[0..2], 16).ok()?;
let g = u8::from_str_radix(&hex[2..4], 16).ok()?;
let b = u8::from_str_radix(&hex[4..6], 16).ok()?;
Some(Color::Rgb(r, g, b))
}
impl Preset {
fn hexes(self) -> &'static [&'static str] {
match self {
Preset::NeonCyber => &["#00E5FF", "#7B5CFF", "#FF5AD9"],
Preset::ArcticTech => &["#00E5FF", "#3A7BFF", "#E6F6FF"],
Preset::SunsetNeon => &["#FF8A00", "#FF4FD8", "#7B5CFF"],
Preset::ForestSky => &["#22C55E", "#14B8A6", "#2563EB"],
Preset::Chrome => &["#F5F5F5", "#BDBDBD", "#6B7280", "#E5E7EB"],
Preset::CrtAmber => &["#FFB000", "#FF8C00", "#7A3E00"],
Preset::OceanFlow => &["#2563EB", "#0EA5A4", "#5EEAD4"],
Preset::DeepSpace => &["#1E3A8A", "#5B21B6", "#312E81"],
Preset::FireWarning => &["#FACC15", "#FB923C", "#EF4444"],
Preset::WarmLuxury => &["#FF5AD9", "#FF8FAB", "#FFD166"],
Preset::EarthTone => &["#E6CCB2", "#B08968", "#6B705C"],
Preset::RoyalPurple => &["#E9D5FF", "#A855F7", "#581C87"],
Preset::Matrix => &["#00FF9C", "#00C46A", "#003B24"],
Preset::AuroraFlux => &["#34FFD2", "#4F9DFF", "#7B61FF", "#C77DFF"],
}
}
}