rae 0.1.2

Renderer-neutral widget, layout, state, and GLSL shader primitives for agentic Rust desktop tools.
Documentation
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Rgba {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32,
}

impl Rgba {
    pub const BLACK: Self = Self::rgb8(0, 0, 0);
    pub const WHITE: Self = Self::rgb8(255, 255, 255);

    pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
        Self { r, g, b, a }
    }

    pub const fn rgb8(r: u8, g: u8, b: u8) -> Self {
        Self {
            r: r as f32 / 255.0,
            g: g as f32 / 255.0,
            b: b as f32 / 255.0,
            a: 1.0,
        }
    }

    pub const fn rgba8(r: u8, g: u8, b: u8, a: u8) -> Self {
        Self {
            r: r as f32 / 255.0,
            g: g as f32 / 255.0,
            b: b as f32 / 255.0,
            a: a as f32 / 255.0,
        }
    }

    pub fn with_alpha(self, alpha: f32) -> Self {
        Self { a: alpha, ..self }
    }

    pub fn mix(self, other: Self, amount: f32) -> Self {
        let amount = amount.clamp(0.0, 1.0);
        Self {
            r: self.r + (other.r - self.r) * amount,
            g: self.g + (other.g - self.g) * amount,
            b: self.b + (other.b - self.b) * amount,
            a: self.a + (other.a - self.a) * amount,
        }
    }

    pub fn to_array(self) -> [f32; 4] {
        [self.r, self.g, self.b, self.a]
    }
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Palette {
    pub name: String,
    pub background: Rgba,
    pub panel: Rgba,
    pub panel_hot: Rgba,
    pub text: Rgba,
    pub muted: Rgba,
    pub accent: Rgba,
    pub success: Rgba,
    pub warning: Rgba,
    pub error: Rgba,
}

impl Palette {
    pub fn xrae() -> Self {
        Self {
            name: "xrae-dark".to_string(),
            background: Rgba::rgb8(3, 5, 14),
            panel: Rgba::rgba8(8, 13, 28, 226),
            panel_hot: Rgba::rgba8(19, 31, 62, 236),
            text: Rgba::rgb8(225, 235, 255),
            muted: Rgba::rgb8(119, 139, 168),
            accent: Rgba::rgb8(122, 185, 255),
            success: Rgba::rgb8(83, 225, 147),
            warning: Rgba::rgb8(255, 190, 94),
            error: Rgba::rgb8(255, 105, 105),
        }
    }
}