rustyle_css/css/
spacing.rs

1//! CSS spacing utilities
2//!
3//! Provides type-safe spacing definitions including scales and responsive spacing.
4//!
5//! # Examples
6//!
7//! ```rust
8//! use rustyle_css::{Spacing, Length};
9//!
10//! // Create spacing values
11//! let padding = Spacing::all(Length::rem(1.0));
12//! let margin = Spacing::vh(Length::rem(0.5), Length::rem(1.0));
13//! let custom = Spacing::custom(
14//!     Length::rem(1.0), // top
15//!     Length::rem(2.0), // right
16//!     Length::rem(1.0), // bottom
17//!     Length::rem(2.0), // left
18//! );
19//! ```
20
21use super::units::Length;
22
23/// Represents CSS spacing (padding, margin, etc.)
24#[derive(Clone, Debug)]
25pub enum Spacing {
26    /// Single value (all sides)
27    All(Length),
28    /// Vertical and horizontal
29    VH(Length, Length),
30    /// Top, horizontal, bottom
31    THB(Length, Length, Length),
32    /// Top, right, bottom, left
33    TRBL(Length, Length, Length, Length),
34}
35
36impl Spacing {
37    /// Create spacing for all sides
38    pub fn all(value: Length) -> Self {
39        Self::All(value)
40    }
41
42    /// Create vertical and horizontal spacing
43    pub fn vh(vertical: Length, horizontal: Length) -> Self {
44        Self::VH(vertical, horizontal)
45    }
46
47    /// Create top, horizontal, bottom spacing
48    pub fn thb(top: Length, horizontal: Length, bottom: Length) -> Self {
49        Self::THB(top, horizontal, bottom)
50    }
51
52    /// Create top, right, bottom, left spacing
53    pub fn trbl(top: Length, right: Length, bottom: Length, left: Length) -> Self {
54        Self::TRBL(top, right, bottom, left)
55    }
56
57    /// Convert to CSS string
58    pub fn to_css(&self) -> String {
59        match self {
60            Spacing::All(v) => v.to_css(),
61            Spacing::VH(v, h) => format!("{} {}", v.to_css(), h.to_css()),
62            Spacing::THB(t, h, b) => format!("{} {} {}", t.to_css(), h.to_css(), b.to_css()),
63            Spacing::TRBL(t, r, b, l) => {
64                format!(
65                    "{} {} {} {}",
66                    t.to_css(),
67                    r.to_css(),
68                    b.to_css(),
69                    l.to_css()
70                )
71            }
72        }
73    }
74}
75
76/// Represents CSS margin
77pub type Margin = Spacing;
78
79/// Represents CSS padding
80pub type Padding = Spacing;
81
82/// Represents CSS border radius
83#[derive(Clone, Debug)]
84pub enum Radius {
85    /// Single value (all corners)
86    All(Length),
87    /// Top-left/bottom-right and top-right/bottom-left
88    VH(Length, Length),
89    /// Top-left, top-right/bottom-left, bottom-right
90    THB(Length, Length, Length),
91    /// Top-left, top-right, bottom-right, bottom-left
92    TRBL(Length, Length, Length, Length),
93}
94
95impl Radius {
96    /// Create radius for all corners
97    pub fn all(value: Length) -> Self {
98        Self::All(value)
99    }
100
101    /// Create vertical and horizontal radius
102    pub fn vh(vertical: Length, horizontal: Length) -> Self {
103        Self::VH(vertical, horizontal)
104    }
105
106    /// Convert to CSS string
107    pub fn to_css(&self) -> String {
108        match self {
109            Radius::All(v) => v.to_css(),
110            Radius::VH(v, h) => format!("{} {}", v.to_css(), h.to_css()),
111            Radius::THB(t, h, b) => format!("{} {} {}", t.to_css(), h.to_css(), b.to_css()),
112            Radius::TRBL(t, r, b, l) => {
113                format!(
114                    "{} {} {} {}",
115                    t.to_css(),
116                    r.to_css(),
117                    b.to_css(),
118                    l.to_css()
119                )
120            }
121        }
122    }
123}
124
125// Re-export SpacingTokens as SpacingScale for convenience
126pub use crate::tokens::spacing::SpacingTokens as SpacingScale;
127
128/// Responsive spacing that adapts to breakpoints
129#[derive(Clone, Debug)]
130pub struct ResponsiveSpacing {
131    pub mobile: Spacing,
132    pub tablet: Option<Spacing>,
133    pub desktop: Option<Spacing>,
134}
135
136impl ResponsiveSpacing {
137    /// Create responsive spacing
138    pub fn new(mobile: Spacing, tablet: Option<Spacing>, desktop: Option<Spacing>) -> Self {
139        Self {
140            mobile,
141            tablet,
142            desktop,
143        }
144    }
145
146    /// Convert to CSS with media queries
147    pub fn to_css(&self, class_name: &str) -> String {
148        let mut css = format!(".{} {{ padding: {}; }}\n", class_name, self.mobile.to_css());
149
150        if let Some(tablet) = &self.tablet {
151            css.push_str(&format!(
152                "@media (min-width: 768px) {{ .{} {{ padding: {}; }} }}\n",
153                class_name,
154                tablet.to_css()
155            ));
156        }
157
158        if let Some(desktop) = &self.desktop {
159            css.push_str(&format!(
160                "@media (min-width: 1024px) {{ .{} {{ padding: {}; }} }}\n",
161                class_name,
162                desktop.to_css()
163            ));
164        }
165
166        css
167    }
168}