rustyle_css/css/
typography.rs

1//! CSS typography utilities
2//!
3//! Provides type-safe typography definitions including font families, sizes, weights, and line heights.
4
5use super::units::Length;
6
7/// Font size
8#[derive(Clone, Debug)]
9pub enum FontSize {
10    /// Length value
11    Length(Length),
12    /// Named size (small, medium, large, etc.)
13    Named(String),
14}
15
16impl FontSize {
17    /// Create from length
18    pub fn length(length: Length) -> Self {
19        Self::Length(length)
20    }
21
22    /// Create from named size
23    pub fn named(name: &str) -> Self {
24        Self::Named(name.to_string())
25    }
26
27    /// Convert to CSS string
28    pub fn to_css(&self) -> String {
29        match self {
30            FontSize::Length(l) => l.to_css(),
31            FontSize::Named(n) => n.clone(),
32        }
33    }
34}
35
36/// Font weight
37#[derive(Clone, Debug)]
38pub enum FontWeight {
39    /// Numeric weight (100-900)
40    Numeric(u16),
41    /// Named weight
42    Named(String),
43}
44
45impl FontWeight {
46    /// Create numeric weight
47    pub fn numeric(value: u16) -> Self {
48        Self::Numeric(value)
49    }
50
51    /// Create named weight
52    pub fn named(name: &str) -> Self {
53        Self::Named(name.to_string())
54    }
55
56    /// Convert to CSS string
57    pub fn to_css(&self) -> String {
58        match self {
59            FontWeight::Numeric(n) => n.to_string(),
60            FontWeight::Named(n) => n.clone(),
61        }
62    }
63}
64
65/// Line height
66#[derive(Clone, Debug)]
67pub enum LineHeight {
68    /// Length value
69    Length(Length),
70    /// Number (unitless)
71    Number(f32),
72    /// Named value
73    Named(String),
74}
75
76impl LineHeight {
77    /// Create from length
78    pub fn length(length: Length) -> Self {
79        Self::Length(length)
80    }
81
82    /// Create from number
83    pub fn number(value: f32) -> Self {
84        Self::Number(value)
85    }
86
87    /// Create from named value
88    pub fn named(name: &str) -> Self {
89        Self::Named(name.to_string())
90    }
91
92    /// Convert to CSS string
93    pub fn to_css(&self) -> String {
94        match self {
95            LineHeight::Length(l) => l.to_css(),
96            LineHeight::Number(n) => n.to_string(),
97            LineHeight::Named(n) => n.clone(),
98        }
99    }
100}
101
102// Re-export types from tokens for convenience
103pub use crate::tokens::typography::{FontFamily, FontSizeScale as TypographyScale};
104
105/// Complete text style builder
106#[derive(Clone, Debug)]
107pub struct TextStyle {
108    pub font_family: Option<String>,
109    pub font_size: Option<FontSize>,
110    pub font_weight: Option<FontWeight>,
111    pub line_height: Option<LineHeight>,
112    pub letter_spacing: Option<Length>,
113}
114
115impl TextStyle {
116    /// Create a new text style
117    pub fn new() -> Self {
118        Self {
119            font_family: None,
120            font_size: None,
121            font_weight: None,
122            line_height: None,
123            letter_spacing: None,
124        }
125    }
126
127    /// Set font family
128    pub fn font_family(mut self, family: &str) -> Self {
129        self.font_family = Some(family.to_string());
130        self
131    }
132
133    /// Set font size
134    pub fn font_size(mut self, size: FontSize) -> Self {
135        self.font_size = Some(size);
136        self
137    }
138
139    /// Set font weight
140    pub fn font_weight(mut self, weight: FontWeight) -> Self {
141        self.font_weight = Some(weight);
142        self
143    }
144
145    /// Set line height
146    pub fn line_height(mut self, height: LineHeight) -> Self {
147        self.line_height = Some(height);
148        self
149    }
150
151    /// Set letter spacing
152    pub fn letter_spacing(mut self, spacing: Length) -> Self {
153        self.letter_spacing = Some(spacing);
154        self
155    }
156
157    /// Convert to CSS string
158    pub fn to_css(&self) -> String {
159        let mut props = Vec::new();
160
161        if let Some(ref family) = self.font_family {
162            props.push(format!("font-family: {};", family));
163        }
164
165        if let Some(ref size) = self.font_size {
166            props.push(format!("font-size: {};", size.to_css()));
167        }
168
169        if let Some(ref weight) = self.font_weight {
170            props.push(format!("font-weight: {};", weight.to_css()));
171        }
172
173        if let Some(ref height) = self.line_height {
174            props.push(format!("line-height: {};", height.to_css()));
175        }
176
177        if let Some(ref spacing) = self.letter_spacing {
178            props.push(format!("letter-spacing: {};", spacing.to_css()));
179        }
180
181        props.join(" ")
182    }
183}
184
185impl Default for TextStyle {
186    fn default() -> Self {
187        Self::new()
188    }
189}