Skip to main content

use_ui_component/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4macro_rules! string_newtype {
5    ($name:ident) => {
6        #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
7        pub struct $name(String);
8
9        impl $name {
10            pub fn new(value: impl Into<String>) -> Self {
11                Self(value.into())
12            }
13
14            pub fn as_str(&self) -> &str {
15                &self.0
16            }
17        }
18
19        impl AsRef<str> for $name {
20            fn as_ref(&self) -> &str {
21                self.as_str()
22            }
23        }
24    };
25}
26
27string_newtype!(ComponentName);
28string_newtype!(ComponentId);
29string_newtype!(ComponentPart);
30string_newtype!(ComponentSlot);
31string_newtype!(ComponentVariant);
32
33/// Component size labels.
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
35pub enum ComponentSize {
36    Xs,
37    Sm,
38    Md,
39    Lg,
40    Xl,
41}
42
43impl ComponentSize {
44    pub fn as_str(self) -> &'static str {
45        match self {
46            Self::Xs => "xs",
47            Self::Sm => "sm",
48            Self::Md => "md",
49            Self::Lg => "lg",
50            Self::Xl => "xl",
51        }
52    }
53}
54
55/// Semantic component roles.
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
57pub enum ComponentRole {
58    Container,
59    Content,
60    Control,
61    Input,
62    Navigation,
63    Feedback,
64    Display,
65}
66
67impl ComponentRole {
68    pub fn is_interactive_role(self) -> bool {
69        matches!(self, Self::Control | Self::Input | Self::Navigation)
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::{
76        ComponentId, ComponentName, ComponentPart, ComponentRole, ComponentSize, ComponentSlot,
77        ComponentVariant,
78    };
79
80    #[test]
81    fn creates_component_identity_values() {
82        let name = ComponentName::new("button");
83        let id = ComponentId::new("submit-button");
84        let part = ComponentPart::new("icon");
85        let slot = ComponentSlot::new("leading");
86        let variant = ComponentVariant::new("primary");
87
88        assert_eq!(name.as_str(), "button");
89        assert_eq!(id.as_str(), "submit-button");
90        assert_eq!(part.as_str(), "icon");
91        assert_eq!(slot.as_str(), "leading");
92        assert_eq!(variant.as_str(), "primary");
93    }
94
95    #[test]
96    fn checks_component_metadata_enums() {
97        assert_eq!(ComponentSize::Md.as_str(), "md");
98        assert!(ComponentRole::Control.is_interactive_role());
99        assert!(!ComponentRole::Display.is_interactive_role());
100    }
101}