mew_css/
properties.rs

1//! # CSS Properties Module
2//!
3//! This module defines the CSS properties that can be set on a style. It provides
4//! a structured way to create and manage CSS properties with type safety.
5//!
6//! ## Module Organization
7//!
8//! The properties are organized into submodules by category:
9//!
10//! - `color`: Color-related properties (color, background-color)
11//! - `size`: Size-related properties (width, height, margin, padding)
12//! - `display`: Display and positioning properties
13//! - `font`: Typography-related properties
14//! - `border`: Border and outline properties
15//! - `position`: Positioning properties (top, right, bottom, left)
16//! - `layout`: General layout properties (overflow, visibility)
17//! - `flex`: Flexbox-specific properties
18//! - `grid`: Grid-specific properties
19//! - `transition`: Transition and animation properties
20//!
21//! ## Usage
22//!
23//! While you can use this module directly to create properties, it's generally
24//! easier to use the methods on the `Style` struct, which will call these
25//! functions for you.
26//!
27//! ```rust
28//! use mew_css::properties::{Property, color};
29//! use mew_css::values::Color;
30//!
31//! // Direct usage
32//! let property = color::color(Color::Blue);
33//!
34//! // More commonly, through the Style API
35//! use mew_css::style;
36//! let css = style().color(Color::Blue).apply();
37//! ```
38
39use crate::values::*;
40use std::fmt;
41
42/// Represents a single CSS property with a name and value.
43///
44/// A `Property` is the fundamental building block of CSS styles in this library.
45/// Each property has a name (like "color" or "margin-top") and a value that has
46/// been converted to a string representation.
47///
48/// Properties are typically created using the functions in the submodules of this
49/// module, rather than being constructed directly.
50///
51/// # Examples
52///
53/// ```rust
54/// use mew_css::properties::Property;
55///
56/// // Create a property directly
57/// let color_prop = Property::new("color", "blue");
58/// let font_size_prop = Property::new("font-size", "16px");
59///
60/// // The string representation includes the semicolon
61/// assert_eq!(color_prop.to_string(), "color: blue;");
62/// ```
63#[derive(Debug, Clone)]
64pub struct Property {
65    /// The CSS property name (e.g., "color", "margin-top")
66    name: String,
67    /// The CSS property value as a string (e.g., "blue", "20px")
68    value: String,
69}
70
71impl Property {
72    /// Creates a new CSS property with the given name and value.
73    ///
74    /// This method converts the value to a string using the `Display` trait.
75    ///
76    /// # Arguments
77    ///
78    /// * `name` - The CSS property name
79    /// * `value` - The property value, which can be any type that implements `Display`
80    ///
81    /// # Returns
82    ///
83    /// A new `Property` instance
84    ///
85    /// # Examples
86    ///
87    /// ```rust
88    /// use mew_css::properties::Property;
89    ///
90    /// let color_prop = Property::new("color", "blue");
91    /// let margin_prop = Property::new("margin", "10px");
92    /// let opacity_prop = Property::new("opacity", 0.5);
93    /// ```
94    pub fn new<T: fmt::Display>(name: &str, value: T) -> Self {
95        Self {
96            name: name.to_string(),
97            value: value.to_string(),
98        }
99    }
100}
101
102impl fmt::Display for Property {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        write!(f, "{}: {};", self.name, self.value)
105    }
106}
107
108/// Color-related CSS properties.
109///
110/// This module provides functions for creating color-related CSS properties
111/// such as text color, background color, and border color.
112pub mod color {
113    use super::*;
114
115    /// Creates a CSS `color` property for setting text color.
116    ///
117    /// The `color` property sets the color of text content and text decorations.
118    ///
119    /// # Arguments
120    ///
121    /// * `value` - The color value to use
122    ///
123    /// # Returns
124    ///
125    /// A new `Property` instance representing the color property
126    ///
127    /// # Examples
128    ///
129    /// ```rust
130    /// use mew_css::properties::color;
131    /// use mew_css::values::Color;
132    ///
133    /// let prop = color::color(Color::Blue);
134    /// assert_eq!(prop.to_string(), "color: blue;");
135    ///
136    /// let prop = color::color(Color::Rgb(255, 0, 0));
137    /// assert_eq!(prop.to_string(), "color: rgb(255, 0, 0);");
138    /// ```
139    pub fn color(value: Color) -> Property {
140        Property::new("color", value)
141    }
142
143    /// Creates a CSS `background-color` property for setting element background color.
144    ///
145    /// The `background-color` property sets the background color of an element.
146    /// The background covers the element's content, padding, and border areas.
147    ///
148    /// # Arguments
149    ///
150    /// * `value` - The color value to use
151    ///
152    /// # Returns
153    ///
154    /// A new `Property` instance representing the background-color property
155    ///
156    /// # Examples
157    ///
158    /// ```rust
159    /// use mew_css::properties::color;
160    /// use mew_css::values::Color;
161    ///
162    /// let prop = color::background_color(Color::LightGray);
163    /// assert_eq!(prop.to_string(), "background-color: lightgray;");
164    ///
165    /// let prop = color::background_color(Color::Rgba(240, 240, 240, 0.5));
166    /// assert_eq!(prop.to_string(), "background-color: rgba(240, 240, 240, 0.5);");
167    /// ```
168    pub fn background_color(value: Color) -> Property {
169        Property::new("background-color", value)
170    }
171
172    /// Creates a CSS `border-color` property for setting element border color.
173    ///
174    /// The `border-color` property sets the color of an element's border on all sides.
175    /// It only has a visible effect when the border style is not `none`.
176    ///
177    /// # Arguments
178    ///
179    /// * `value` - The color value to use
180    ///
181    /// # Returns
182    ///
183    /// A new `Property` instance representing the border-color property
184    ///
185    /// # Examples
186    ///
187    /// ```rust
188    /// use mew_css::properties::color;
189    /// use mew_css::values::Color;
190    ///
191    /// let prop = color::border_color(Color::Black);
192    /// assert_eq!(prop.to_string(), "border-color: black;");
193    /// ```
194    pub fn border_color(value: Color) -> Property {
195        Property::new("border-color", value)
196    }
197}
198
199/// Size properties
200pub mod size {
201    use super::*;
202
203    /// Create a width property
204    pub fn width(value: Size) -> Property {
205        Property::new("width", value)
206    }
207
208    /// Create a height property
209    pub fn height(value: Size) -> Property {
210        Property::new("height", value)
211    }
212
213    /// Create a margin property
214    pub fn margin(value: Size) -> Property {
215        Property::new("margin", value)
216    }
217
218    /// Create a margin-top property
219    pub fn margin_top(value: Size) -> Property {
220        Property::new("margin-top", value)
221    }
222
223    /// Create a margin-right property
224    pub fn margin_right(value: Size) -> Property {
225        Property::new("margin-right", value)
226    }
227
228    /// Create a margin-bottom property
229    pub fn margin_bottom(value: Size) -> Property {
230        Property::new("margin-bottom", value)
231    }
232
233    /// Create a margin-left property
234    pub fn margin_left(value: Size) -> Property {
235        Property::new("margin-left", value)
236    }
237
238    /// Create a padding property
239    pub fn padding(value: Size) -> Property {
240        Property::new("padding", value)
241    }
242
243    /// Create a padding-top property
244    pub fn padding_top(value: Size) -> Property {
245        Property::new("padding-top", value)
246    }
247
248    /// Create a padding-right property
249    pub fn padding_right(value: Size) -> Property {
250        Property::new("padding-right", value)
251    }
252
253    /// Create a padding-bottom property
254    pub fn padding_bottom(value: Size) -> Property {
255        Property::new("padding-bottom", value)
256    }
257
258    /// Create a padding-left property
259    pub fn padding_left(value: Size) -> Property {
260        Property::new("padding-left", value)
261    }
262
263    /// Create a font-size property
264    pub fn font_size(value: Size) -> Property {
265        Property::new("font-size", value)
266    }
267
268    /// Create a line-height property
269    pub fn line_height(value: Size) -> Property {
270        Property::new("line-height", value)
271    }
272
273    /// Create a border-width property
274    pub fn border_width(value: Size) -> Property {
275        Property::new("border-width", value)
276    }
277}
278
279/// Display properties
280pub mod display {
281    use super::*;
282
283    /// Create a display property
284    pub fn display(value: Display) -> Property {
285        Property::new("display", value)
286    }
287
288    /// Create a position property
289    pub fn position(value: Position) -> Property {
290        Property::new("position", value)
291    }
292
293    /// Create a flex-direction property
294    pub fn flex_direction(value: FlexDirection) -> Property {
295        Property::new("flex-direction", value)
296    }
297
298    /// Create a justify-content property
299    pub fn justify_content(value: JustifyContent) -> Property {
300        Property::new("justify-content", value)
301    }
302
303    /// Create an align-items property
304    pub fn align_items(value: AlignItems) -> Property {
305        Property::new("align-items", value)
306    }
307}
308
309/// Font properties
310pub mod font {
311    use super::*;
312
313    /// Create a font-weight property
314    pub fn font_weight(value: FontWeight) -> Property {
315        Property::new("font-weight", value)
316    }
317
318    /// Create a font-family property
319    pub fn font_family(value: &str) -> Property {
320        Property::new("font-family", value)
321    }
322
323    /// Create a text-align property
324    pub fn text_align(value: TextAlign) -> Property {
325        Property::new("text-align", value)
326    }
327
328    /// Create a font-size property with FontSize enum
329    pub fn font_size_enum(value: FontSize) -> Property {
330        Property::new("font-size", value)
331    }
332
333    /// Create a line-height property with LineHeight enum
334    pub fn line_height_enum(value: LineHeight) -> Property {
335        Property::new("line-height", value)
336    }
337
338    /// Create a text-decoration property
339    pub fn text_decoration(value: TextDecoration) -> Property {
340        Property::new("text-decoration", value)
341    }
342}
343
344/// Border properties
345pub mod border {
346    use super::*;
347
348    /// Create a border-style property
349    pub fn border_style(value: BorderStyle) -> Property {
350        Property::new("border-style", value)
351    }
352
353    /// Create a border-radius property
354    pub fn border_radius(value: Size) -> Property {
355        Property::new("border-radius", value)
356    }
357
358    /// Create a border property (shorthand)
359    pub fn border(width: Size, style: BorderStyle, color: Color) -> Property {
360        Property::new("border", format!("{} {} {}", width, style, color))
361    }
362
363    /// Create a border-top property (shorthand)
364    pub fn border_top(width: Size, style: BorderStyle, color: Color) -> Property {
365        Property::new("border-top", format!("{} {} {}", width, style, color))
366    }
367
368    /// Create a border-right property (shorthand)
369    pub fn border_right(width: Size, style: BorderStyle, color: Color) -> Property {
370        Property::new("border-right", format!("{} {} {}", width, style, color))
371    }
372
373    /// Create a border-bottom property (shorthand)
374    pub fn border_bottom(width: Size, style: BorderStyle, color: Color) -> Property {
375        Property::new("border-bottom", format!("{} {} {}", width, style, color))
376    }
377
378    /// Create a border-left property (shorthand)
379    pub fn border_left(width: Size, style: BorderStyle, color: Color) -> Property {
380        Property::new("border-left", format!("{} {} {}", width, style, color))
381    }
382
383    /// Create a box-shadow property
384    pub fn box_shadow(value: BoxShadow) -> Property {
385        Property::new("box-shadow", value)
386    }
387
388    /// Create a box-shadow property with none value
389    pub fn box_shadow_none() -> Property {
390        Property::new("box-shadow", "none")
391    }
392}
393
394/// Position properties
395pub mod position {
396    use super::*;
397
398    /// Create a top property
399    pub fn top(value: Size) -> Property {
400        Property::new("top", value)
401    }
402
403    /// Create a right property
404    pub fn right(value: Size) -> Property {
405        Property::new("right", value)
406    }
407
408    /// Create a bottom property
409    pub fn bottom(value: Size) -> Property {
410        Property::new("bottom", value)
411    }
412
413    /// Create a left property
414    pub fn left(value: Size) -> Property {
415        Property::new("left", value)
416    }
417
418    /// Create a z-index property
419    pub fn z_index(value: ZIndex) -> Property {
420        Property::new("z-index", value)
421    }
422}
423
424/// Layout properties
425pub mod layout {
426    use super::*;
427
428    /// Create an overflow property
429    pub fn overflow(value: Overflow) -> Property {
430        Property::new("overflow", value)
431    }
432
433    /// Create an overflow-x property
434    pub fn overflow_x(value: Overflow) -> Property {
435        Property::new("overflow-x", value)
436    }
437
438    /// Create an overflow-y property
439    pub fn overflow_y(value: Overflow) -> Property {
440        Property::new("overflow-y", value)
441    }
442
443    /// Create a visibility property
444    pub fn visibility(value: Visibility) -> Property {
445        Property::new("visibility", value)
446    }
447
448    /// Create an opacity property
449    pub fn opacity(value: f32) -> Property {
450        // Ensure opacity is between 0 and 1
451        let clamped = value.max(0.0).min(1.0);
452        Property::new("opacity", clamped)
453    }
454
455    /// Create a cursor property
456    pub fn cursor(value: Cursor) -> Property {
457        Property::new("cursor", value)
458    }
459}
460
461/// Flex properties
462pub mod flex {
463    use super::*;
464
465    /// Create a gap property
466    pub fn gap(value: Size) -> Property {
467        Property::new("gap", value)
468    }
469
470    /// Create a row-gap property
471    pub fn row_gap(value: Size) -> Property {
472        Property::new("row-gap", value)
473    }
474
475    /// Create a column-gap property
476    pub fn column_gap(value: Size) -> Property {
477        Property::new("column-gap", value)
478    }
479}
480
481/// Grid properties
482pub mod grid {
483    use super::*;
484
485    /// Create a grid-template-columns property
486    pub fn grid_template_columns(value: &str) -> Property {
487        Property::new("grid-template-columns", value)
488    }
489
490    /// Create a grid-template-rows property
491    pub fn grid_template_rows(value: &str) -> Property {
492        Property::new("grid-template-rows", value)
493    }
494}
495
496/// Transition properties
497pub mod transition {
498    use super::*;
499
500    /// Create a transition property
501    pub fn transition(value: Transition) -> Property {
502        Property::new("transition", value)
503    }
504
505    /// Create a transition property with none value
506    pub fn transition_none() -> Property {
507        Property::new("transition", "none")
508    }
509
510    /// Create a transition property with all value
511    pub fn transition_all(duration: f32, timing_function: Option<&str>, delay: Option<f32>) -> Property {
512        let mut value = format!("all {}s", duration);
513
514        if let Some(timing) = timing_function {
515            value.push_str(&format!(" {}", timing));
516        }
517
518        if let Some(delay_val) = delay {
519            value.push_str(&format!(" {}s", delay_val));
520        }
521
522        Property::new("transition", value)
523    }
524}
525
526/// Size properties extension
527pub mod size_ext {
528    use super::*;
529
530    /// Create a max-width property
531    pub fn max_width(value: Size) -> Property {
532        Property::new("max-width", value)
533    }
534
535    /// Create a min-width property
536    pub fn min_width(value: Size) -> Property {
537        Property::new("min-width", value)
538    }
539
540    /// Create a max-height property
541    pub fn max_height(value: Size) -> Property {
542        Property::new("max-height", value)
543    }
544
545    /// Create a min-height property
546    pub fn min_height(value: Size) -> Property {
547        Property::new("min-height", value)
548    }
549}