use-theme 0.1.0

Theme identity and mode primitives for RustUse UI
Documentation
#![forbid(unsafe_code)]
#![doc = include_str!("../README.md")]

/// Theme display mode.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum ThemeMode {
    Light,
    Dark,
    System,
}

impl ThemeMode {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Light => "light",
            Self::Dark => "dark",
            Self::System => "system",
        }
    }

    pub fn is_explicit(self) -> bool {
        !matches!(self, Self::System)
    }
}

/// A theme name.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ThemeName(String);

impl ThemeName {
    pub fn new(value: impl Into<String>) -> Self {
        Self(value.into())
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl AsRef<str> for ThemeName {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

/// A named theme variant.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct ThemeVariant(String);

impl ThemeVariant {
    pub fn new(value: impl Into<String>) -> Self {
        Self(value.into())
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl AsRef<str> for ThemeVariant {
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}

/// Semantic roles commonly used by themes.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum SemanticThemeRole {
    Background,
    Foreground,
    Primary,
    Secondary,
    Accent,
    Muted,
    Success,
    Warning,
    Danger,
    Info,
}

impl SemanticThemeRole {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Background => "background",
            Self::Foreground => "foreground",
            Self::Primary => "primary",
            Self::Secondary => "secondary",
            Self::Accent => "accent",
            Self::Muted => "muted",
            Self::Success => "success",
            Self::Warning => "warning",
            Self::Danger => "danger",
            Self::Info => "info",
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{SemanticThemeRole, ThemeMode, ThemeName, ThemeVariant};

    #[test]
    fn creates_theme_identity_values() {
        let name = ThemeName::new("Acme");
        let variant = ThemeVariant::new("high-contrast");

        assert_eq!(name.as_str(), "Acme");
        assert_eq!(variant.as_str(), "high-contrast");
    }

    #[test]
    fn exposes_theme_mode_and_role_labels() {
        assert_eq!(ThemeMode::Dark.as_str(), "dark");
        assert!(ThemeMode::Light.is_explicit());
        assert!(!ThemeMode::System.is_explicit());
        assert_eq!(SemanticThemeRole::Danger.as_str(), "danger");
    }
}