use-ui-component 0.1.0

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

macro_rules! string_newtype {
    ($name:ident) => {
        #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
        pub struct $name(String);

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

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

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

string_newtype!(ComponentName);
string_newtype!(ComponentId);
string_newtype!(ComponentPart);
string_newtype!(ComponentSlot);
string_newtype!(ComponentVariant);

/// Component size labels.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum ComponentSize {
    Xs,
    Sm,
    Md,
    Lg,
    Xl,
}

impl ComponentSize {
    pub fn as_str(self) -> &'static str {
        match self {
            Self::Xs => "xs",
            Self::Sm => "sm",
            Self::Md => "md",
            Self::Lg => "lg",
            Self::Xl => "xl",
        }
    }
}

/// Semantic component roles.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum ComponentRole {
    Container,
    Content,
    Control,
    Input,
    Navigation,
    Feedback,
    Display,
}

impl ComponentRole {
    pub fn is_interactive_role(self) -> bool {
        matches!(self, Self::Control | Self::Input | Self::Navigation)
    }
}

#[cfg(test)]
mod tests {
    use super::{
        ComponentId, ComponentName, ComponentPart, ComponentRole, ComponentSize, ComponentSlot,
        ComponentVariant,
    };

    #[test]
    fn creates_component_identity_values() {
        let name = ComponentName::new("button");
        let id = ComponentId::new("submit-button");
        let part = ComponentPart::new("icon");
        let slot = ComponentSlot::new("leading");
        let variant = ComponentVariant::new("primary");

        assert_eq!(name.as_str(), "button");
        assert_eq!(id.as_str(), "submit-button");
        assert_eq!(part.as_str(), "icon");
        assert_eq!(slot.as_str(), "leading");
        assert_eq!(variant.as_str(), "primary");
    }

    #[test]
    fn checks_component_metadata_enums() {
        assert_eq!(ComponentSize::Md.as_str(), "md");
        assert!(ComponentRole::Control.is_interactive_role());
        assert!(!ComponentRole::Display.is_interactive_role());
    }
}