1.9 KiB · text History af1c436
//! Named colours from the house palettes.
//!
//! Nothing in here is typed by hand: `generated.rs` is produced by
//! `tools/regen_palettes.py`, which reads the neiam themes out of the dms
//! stylesheet and carries the Casabeza values recovered from the cbzauth APK.

mod generated;

pub use generated::THEMES;

/// One semantic slot in a theme, e.g. `primary` or `base-content`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct NamedColor {
    pub role: &'static str,
    pub rgb: [u8; 3],
}

#[derive(Clone, Copy)]
pub struct Theme {
    pub name: &'static str,
    pub light: bool,
    pub colors: &'static [NamedColor],
}

impl Theme {
    pub fn get(&self, role: &str) -> Option<NamedColor> {
        self.colors.iter().copied().find(|c| c.role == role)
    }

    /// The roles worth offering as a foreground or background pick, in a
    /// stable order so the combination grid does not reshuffle between themes.
    pub fn swatches(&self) -> Vec<NamedColor> {
        const ORDER: &[&str] = &[
            "primary",
            "accent",
            "secondary",
            "base-100",
            "base-200",
            "base-300",
            "base-content",
            "neutral",
            "info",
            "success",
            "warning",
            "error",
            "primary-content",
            "accent-content",
            "secondary-content",
            "neutral-content",
        ];
        let mut out: Vec<NamedColor> = ORDER.iter().filter_map(|r| self.get(r)).collect();
        // Anything the stylesheet defines that ORDER does not know about still
        // belongs in the picker; a new daisyUI role should not vanish silently.
        for c in self.colors {
            if !out.iter().any(|o| o.role == c.role) {
                out.push(*c);
            }
        }
        out
    }
}

pub fn theme_by_name(name: &str) -> Option<&'static Theme> {
    THEMES.iter().find(|t| t.name == name)
}