mew_css/
style.rs

1//! # Style Builder Module
2//!
3//! This module provides a fluent API for building CSS styles with strong typing.
4//! It forms the core of the Mew CSS library, allowing you to chain method calls
5//! to build complex CSS styles in a type-safe manner.
6//!
7//! ## Design Philosophy
8//!
9//! The style builder follows a fluent interface pattern where each method returns
10//! a mutable reference to self, allowing for method chaining. This creates a clean,
11//! declarative API that mimics the structure of CSS itself while providing the
12//! benefits of Rust's type system.
13//!
14//! ## Usage Patterns
15//!
16//! ### Basic Style Creation
17//!
18//! ```rust
19//! use mew_css::style;
20//! use mew_css::values::{Color, Size};
21//!
22//! let css = style()
23//!     .color(Color::Blue)
24//!     .font_size(Size::Px(16))
25//!     .apply();
26//! ```
27//!
28//! ### Custom Properties
29//!
30//! ```rust
31//! use mew_css::style;
32//!
33//! let css = style()
34//!     .custom_property("animation-name", "fade-in")
35//!     .custom_property("animation-duration", "2s")
36//!     .apply();
37//! ```
38//!
39//! ### CSS Variables
40//!
41//! ```rust
42//! use mew_css::style;
43//!
44//! let css = style()
45//!     .set_var("primary-color", "#3366ff")
46//!     .set_var("spacing", "1rem")
47//!     .apply();
48//! ```
49
50use crate::properties::{Property, color, size, display, font, border, position, layout, flex, grid, transition, size_ext};
51use crate::values::*;
52use std::fmt;
53
54/// A CSS style builder that provides a fluent API for creating CSS styles.
55///
56/// The `Style` struct is the main entry point for building CSS styles. It maintains
57/// an internal collection of CSS properties and provides methods for adding and
58/// manipulating these properties. The fluent API design allows for chaining method
59/// calls to create complex styles in a readable, declarative manner.
60///
61/// # Examples
62///
63/// Basic usage:
64///
65/// ```rust
66/// use mew_css::style;
67/// use mew_css::values::{Color, Size};
68///
69/// let css = style()
70///     .color(Color::Blue)
71///     .font_size(Size::Px(16))
72///     .apply();
73/// ```
74///
75/// The resulting CSS string will be: `color: blue; font-size: 16px;`
76#[derive(Debug, Default)]
77pub struct Style {
78    /// Collection of CSS properties that make up this style
79    properties: Vec<Property>,
80}
81
82impl Style {
83    /// Creates a new empty style with no properties.
84    ///
85    /// This is the starting point for building a CSS style. After creating a new style,
86    /// you can chain method calls to add properties.
87    ///
88    /// # Examples
89    ///
90    /// ```rust
91    /// use mew_css::style::Style;
92    ///
93    /// let style = Style::new();
94    /// ```
95    ///
96    /// More commonly, you'll use the `style()` function:
97    ///
98    /// ```rust
99    /// use mew_css::style;
100    ///
101    /// let style = style();
102    /// ```
103    pub fn new() -> Self {
104        Self {
105            properties: Vec::new(),
106        }
107    }
108
109    /// Adds a property to the style and returns a mutable reference to self.
110    ///
111    /// This is a low-level method used by the property-specific methods. Most users
112    /// won't need to call this directly, but it's useful for extending the library
113    /// with custom properties.
114    ///
115    /// # Arguments
116    ///
117    /// * `property` - The CSS property to add
118    ///
119    /// # Returns
120    ///
121    /// A mutable reference to self for method chaining
122    ///
123    /// # Examples
124    ///
125    /// ```rust
126    /// use mew_css::style;
127    /// use mew_css::properties::Property;
128    ///
129    /// let css = style()
130    ///     .add_property(Property::new("color", "blue"))
131    ///     .add_property(Property::new("font-size", "16px"))
132    ///     .apply();
133    /// ```
134    pub fn add_property(&mut self, property: Property) -> &mut Self {
135        self.properties.push(property);
136        self
137    }
138
139    /// Generates the final CSS string from all added properties.
140    ///
141    /// This method should be called after adding all desired properties to generate
142    /// the CSS string. It formats each property as `name: value;` and joins them
143    /// with spaces.
144    ///
145    /// # Returns
146    ///
147    /// A string containing the CSS representation of all properties
148    ///
149    /// # Examples
150    ///
151    /// ```rust
152    /// use mew_css::style;
153    /// use mew_css::values::{Color, Size};
154    ///
155    /// let css = style()
156    ///     .color(Color::Blue)
157    ///     .font_size(Size::Px(16))
158    ///     .apply();
159    ///
160    /// assert_eq!(css, "color: blue; font-size: 16px;");
161    /// ```
162    pub fn apply(&self) -> String {
163        self.to_string()
164    }
165
166    /// Alias for `apply()` that generates the CSS string.
167    ///
168    /// This method provides an alternative name that might be more intuitive in some contexts.
169    ///
170    /// # Returns
171    ///
172    /// A string containing the CSS representation of all properties
173    ///
174    /// # Examples
175    ///
176    /// ```rust
177    /// use mew_css::style;
178    /// use mew_css::values::{Color, Size};
179    ///
180    /// let css = style()
181    ///     .color(Color::Blue)
182    ///     .font_size(Size::Px(16))
183    ///     .build();
184    ///
185    /// assert_eq!(css, "color: blue; font-size: 16px;");
186    /// ```
187    pub fn build(&self) -> String {
188        self.apply()
189    }
190
191    /// Adds a custom property with the given name and value.
192    ///
193    /// This method allows you to add any CSS property, including those not explicitly
194    /// supported by the library. It's useful for experimental properties, vendor-prefixed
195    /// properties, or any other property not covered by the built-in methods.
196    ///
197    /// # Arguments
198    ///
199    /// * `name` - The CSS property name
200    /// * `value` - The property value, which can be any type that implements `Display`
201    ///
202    /// # Returns
203    ///
204    /// A mutable reference to self for method chaining
205    ///
206    /// # Examples
207    ///
208    /// ```rust
209    /// use mew_css::style;
210    ///
211    /// let css = style()
212    ///     .custom_property("animation-name", "fade-in")
213    ///     .custom_property("animation-duration", "2s")
214    ///     .apply();
215    ///
216    /// assert_eq!(css, "animation-name: fade-in; animation-duration: 2s;");
217    /// ```
218    pub fn custom_property<T: fmt::Display>(&mut self, name: &str, value: T) -> &mut Self {
219        self.add_property(Property::new(name, value))
220    }
221
222    /// Defines a CSS custom property (CSS variable).
223    ///
224    /// This method adds a CSS variable definition to the style. CSS variables are defined
225    /// with the `--` prefix and can be referenced using the `var()` function.
226    ///
227    /// # Arguments
228    ///
229    /// * `name` - The variable name (with or without the `--` prefix)
230    /// * `value` - The variable value, which can be any type that implements `Display`
231    ///
232    /// # Returns
233    ///
234    /// A mutable reference to self for method chaining
235    ///
236    /// # Examples
237    ///
238    /// ```rust
239    /// use mew_css::style;
240    ///
241    /// let css = style()
242    ///     .set_var("primary-color", "#3366ff")
243    ///     .set_var("spacing", "1rem")
244    ///     .apply();
245    ///
246    /// assert_eq!(css, "--primary-color: #3366ff; --spacing: 1rem;");
247    /// ```
248    ///
249    /// The `--` prefix is added automatically if not present:
250    ///
251    /// ```rust
252    /// use mew_css::style;
253    ///
254    /// let css = style()
255    ///     .set_var("--primary-color", "#3366ff") // With prefix
256    ///     .set_var("spacing", "1rem")            // Without prefix
257    ///     .apply();
258    ///
259    /// assert_eq!(css, "--primary-color: #3366ff; --spacing: 1rem;");
260    /// ```
261    pub fn set_var<T: fmt::Display>(&mut self, name: &str, value: T) -> &mut Self {
262        let var_name = if name.trim().starts_with("--") {
263            name.trim().to_string()
264        } else {
265            format!("--{}", name.trim())
266        };
267        self.custom_property(&var_name, value)
268    }
269
270    // Color properties
271
272    /// Sets the text color of an element.
273    ///
274    /// The `color` property specifies the color of text content and text decorations.
275    /// It can be set using named colors, RGB/RGBA values, HSL/HSLA values, or hex codes.
276    ///
277    /// # Arguments
278    ///
279    /// * `value` - The color value to set
280    ///
281    /// # Returns
282    ///
283    /// A mutable reference to self for method chaining
284    ///
285    /// # Examples
286    ///
287    /// ```rust
288    /// use mew_css::style;
289    /// use mew_css::values::Color;
290    ///
291    /// // Using a named color
292    /// let css1 = style().color(Color::Red).apply();
293    ///
294    /// // Using RGB values
295    /// let css2 = style().color(Color::Rgb(255, 0, 0)).apply();
296    ///
297    /// // Using RGBA values with transparency
298    /// let css3 = style().color(Color::Rgba(255, 0, 0, 0.5)).apply();
299    ///
300    /// // Using a hex color
301    /// let css4 = style().color(Color::Hex("#ff0000".to_string())).apply();
302    /// ```
303    pub fn color(&mut self, value: Color) -> &mut Self {
304        self.add_property(color::color(value))
305    }
306
307    /// Sets the background color of an element.
308    ///
309    /// The `background-color` property sets the background color of an element.
310    /// The background covers the element's content, padding, and border areas.
311    ///
312    /// # Arguments
313    ///
314    /// * `value` - The color value to set
315    ///
316    /// # Returns
317    ///
318    /// A mutable reference to self for method chaining
319    ///
320    /// # Examples
321    ///
322    /// ```rust
323    /// use mew_css::style;
324    /// use mew_css::values::Color;
325    ///
326    /// // Using a named color
327    /// let css1 = style().background_color(Color::LightGray).apply();
328    ///
329    /// // Using RGB values
330    /// let css2 = style().background_color(Color::Rgb(240, 240, 240)).apply();
331    ///
332    /// // Using RGBA values with transparency
333    /// let css3 = style().background_color(Color::Rgba(240, 240, 240, 0.5)).apply();
334    /// ```
335    pub fn background_color(&mut self, value: Color) -> &mut Self {
336        self.add_property(color::background_color(value))
337    }
338
339    /// Set the border-color property
340    pub fn border_color(&mut self, value: Color) -> &mut Self {
341        self.add_property(color::border_color(value))
342    }
343
344    // Size properties
345
346    /// Sets the width of an element.
347    ///
348    /// The `width` property sets the width of an element's content area.
349    /// It can be specified in various units like pixels, percentages, or relative units.
350    ///
351    /// # Arguments
352    ///
353    /// * `value` - The width value to set
354    ///
355    /// # Returns
356    ///
357    /// A mutable reference to self for method chaining
358    ///
359    /// # Examples
360    ///
361    /// ```rust
362    /// use mew_css::style;
363    /// use mew_css::values::Size;
364    ///
365    /// // Fixed width in pixels
366    /// let css1 = style().width(Size::Px(300)).apply();
367    ///
368    /// // Percentage width (relative to parent)
369    /// let css2 = style().width(Size::Percent(100.0)).apply();
370    ///
371    /// // Auto width
372    /// let css3 = style().width(Size::Auto).apply();
373    ///
374    /// // Viewport-relative width
375    /// let css4 = style().width(Size::Vw(50.0)).apply();
376    /// ```
377    pub fn width(&mut self, value: Size) -> &mut Self {
378        self.add_property(size::width(value))
379    }
380
381    /// Sets the height of an element.
382    ///
383    /// The `height` property sets the height of an element's content area.
384    /// Like width, it can be specified in various units.
385    ///
386    /// # Arguments
387    ///
388    /// * `value` - The height value to set
389    ///
390    /// # Returns
391    ///
392    /// A mutable reference to self for method chaining
393    ///
394    /// # Examples
395    ///
396    /// ```rust
397    /// use mew_css::style;
398    /// use mew_css::values::Size;
399    ///
400    /// // Fixed height in pixels
401    /// let css1 = style().height(Size::Px(200)).apply();
402    ///
403    /// // Percentage height (requires parent to have a defined height)
404    /// let css2 = style().height(Size::Percent(100.0)).apply();
405    ///
406    /// // Viewport-relative height
407    /// let css3 = style().height(Size::Vh(100.0)).apply();
408    /// ```
409    pub fn height(&mut self, value: Size) -> &mut Self {
410        self.add_property(size::height(value))
411    }
412
413    /// Sets the margin around an element.
414    ///
415    /// The `margin` property creates space around an element, outside of any defined
416    /// borders. It sets the margin on all four sides at once (top, right, bottom, left).
417    ///
418    /// # Arguments
419    ///
420    /// * `value` - The margin value to set
421    ///
422    /// # Returns
423    ///
424    /// A mutable reference to self for method chaining
425    ///
426    /// # Examples
427    ///
428    /// ```rust
429    /// use mew_css::style;
430    /// use mew_css::values::Size;
431    ///
432    /// // Fixed margin in pixels
433    /// let css1 = style().margin(Size::Px(10)).apply();
434    ///
435    /// // Auto margin (useful for horizontal centering)
436    /// let css2 = style().margin(Size::Auto).apply();
437    ///
438    /// // Relative margin using em
439    /// let css3 = style().margin(Size::Em(1.5)).apply();
440    /// ```
441    ///
442    /// For directional margins, use the specific methods:
443    /// `margin_top()`, `margin_right()`, `margin_bottom()`, `margin_left()`
444    pub fn margin(&mut self, value: Size) -> &mut Self {
445        self.add_property(size::margin(value))
446    }
447
448    /// Set the margin-top property
449    pub fn margin_top(&mut self, value: Size) -> &mut Self {
450        self.add_property(size::margin_top(value))
451    }
452
453    /// Set the margin-right property
454    pub fn margin_right(&mut self, value: Size) -> &mut Self {
455        self.add_property(size::margin_right(value))
456    }
457
458    /// Set the margin-bottom property
459    pub fn margin_bottom(&mut self, value: Size) -> &mut Self {
460        self.add_property(size::margin_bottom(value))
461    }
462
463    /// Set the margin-left property
464    pub fn margin_left(&mut self, value: Size) -> &mut Self {
465        self.add_property(size::margin_left(value))
466    }
467
468    /// Set the padding property
469    pub fn padding(&mut self, value: Size) -> &mut Self {
470        self.add_property(size::padding(value))
471    }
472
473    /// Set the padding-top property
474    pub fn padding_top(&mut self, value: Size) -> &mut Self {
475        self.add_property(size::padding_top(value))
476    }
477
478    /// Set the padding-right property
479    pub fn padding_right(&mut self, value: Size) -> &mut Self {
480        self.add_property(size::padding_right(value))
481    }
482
483    /// Set the padding-bottom property
484    pub fn padding_bottom(&mut self, value: Size) -> &mut Self {
485        self.add_property(size::padding_bottom(value))
486    }
487
488    /// Set the padding-left property
489    pub fn padding_left(&mut self, value: Size) -> &mut Self {
490        self.add_property(size::padding_left(value))
491    }
492
493    /// Set the font-size property
494    pub fn font_size(&mut self, value: Size) -> &mut Self {
495        self.add_property(size::font_size(value))
496    }
497
498    /// Set the line-height property
499    pub fn line_height(&mut self, value: Size) -> &mut Self {
500        self.add_property(size::line_height(value))
501    }
502
503    /// Set the border-width property
504    pub fn border_width(&mut self, value: Size) -> &mut Self {
505        self.add_property(size::border_width(value))
506    }
507
508    // Display properties
509
510    /// Sets how an element is displayed in the layout.
511    ///
512    /// The `display` property determines how an element is treated in the layout flow
513    /// and how its children are laid out. This is one of the most important CSS properties
514    /// for controlling layout.
515    ///
516    /// # Arguments
517    ///
518    /// * `value` - The display value to set
519    ///
520    /// # Returns
521    ///
522    /// A mutable reference to self for method chaining
523    ///
524    /// # Examples
525    ///
526    /// ```rust
527    /// use mew_css::style;
528    /// use mew_css::values::Display;
529    ///
530    /// // Block layout (element takes up full width)
531    /// let css1 = style().display(Display::Block).apply();
532    ///
533    /// // Inline layout (element flows with text)
534    /// let css2 = style().display(Display::Inline).apply();
535    ///
536    /// // Flexbox layout
537    /// let css3 = style().display(Display::Flex).apply();
538    ///
539    /// // Grid layout
540    /// let css4 = style().display(Display::Grid).apply();
541    ///
542    /// // Hide element
543    /// let css5 = style().display(Display::None).apply();
544    /// ```
545    pub fn display(&mut self, value: Display) -> &mut Self {
546        self.add_property(display::display(value))
547    }
548
549    /// Sets the positioning method for an element.
550    ///
551    /// The `position` property specifies how an element is positioned in the document.
552    /// It works together with the `top`, `right`, `bottom`, and `left` properties to
553    /// determine the final position of the element.
554    ///
555    /// # Arguments
556    ///
557    /// * `value` - The position value to set
558    ///
559    /// # Returns
560    ///
561    /// A mutable reference to self for method chaining
562    ///
563    /// # Examples
564    ///
565    /// ```rust
566    /// use mew_css::style;
567    /// use mew_css::values::{Position, Size};
568    ///
569    /// // Static positioning (default flow)
570    /// let css1 = style().position(Position::Static).apply();
571    ///
572    /// // Relative positioning (offset from normal position)
573    /// let css2 = style()
574    ///     .position(Position::Relative)
575    ///     .top(Size::Px(10))
576    ///     .left(Size::Px(20))
577    ///     .apply();
578    ///
579    /// // Absolute positioning (relative to nearest positioned ancestor)
580    /// let css3 = style()
581    ///     .position(Position::Absolute)
582    ///     .top(Size::Px(0))
583    ///     .right(Size::Px(0))
584    ///     .apply();
585    ///
586    /// // Fixed positioning (relative to viewport)
587    /// let css4 = style()
588    ///     .position(Position::Fixed)
589    ///     .bottom(Size::Px(20))
590    ///     .right(Size::Px(20))
591    ///     .apply();
592    /// ```
593    pub fn position(&mut self, value: Position) -> &mut Self {
594        self.add_property(display::position(value))
595    }
596
597    /// Sets the direction of flex items within a flex container.
598    ///
599    /// The `flex-direction` property establishes the main axis of a flex container,
600    /// defining the direction in which flex items are placed. This property only
601    /// applies to elements with `display: flex`.
602    ///
603    /// # Arguments
604    ///
605    /// * `value` - The flex-direction value to set
606    ///
607    /// # Returns
608    ///
609    /// A mutable reference to self for method chaining
610    ///
611    /// # Examples
612    ///
613    /// ```rust
614    /// use mew_css::style;
615    /// use mew_css::values::{Display, FlexDirection};
616    ///
617    /// // Create a horizontal flex container (default)
618    /// let css1 = style()
619    ///     .display(Display::Flex)
620    ///     .flex_direction(FlexDirection::Row)
621    ///     .apply();
622    ///
623    /// // Create a vertical flex container
624    /// let css2 = style()
625    ///     .display(Display::Flex)
626    ///     .flex_direction(FlexDirection::Column)
627    ///     .apply();
628    ///
629    /// // Reverse the order of items
630    /// let css3 = style()
631    ///     .display(Display::Flex)
632    ///     .flex_direction(FlexDirection::RowReverse)
633    ///     .apply();
634    /// ```
635    pub fn flex_direction(&mut self, value: FlexDirection) -> &mut Self {
636        self.add_property(display::flex_direction(value))
637    }
638
639    /// Set the justify-content property
640    pub fn justify_content(&mut self, value: JustifyContent) -> &mut Self {
641        self.add_property(display::justify_content(value))
642    }
643
644    /// Set the align-items property
645    pub fn align_items(&mut self, value: AlignItems) -> &mut Self {
646        self.add_property(display::align_items(value))
647    }
648
649    // Font properties
650
651    /// Set the font-weight property
652    pub fn font_weight(&mut self, value: FontWeight) -> &mut Self {
653        self.add_property(font::font_weight(value))
654    }
655
656    /// Set the font-family property
657    pub fn font_family(&mut self, value: &str) -> &mut Self {
658        self.add_property(font::font_family(value))
659    }
660
661    /// Set the text-align property
662    pub fn text_align(&mut self, value: TextAlign) -> &mut Self {
663        self.add_property(font::text_align(value))
664    }
665
666    /// Set the font-size property with FontSize enum
667    pub fn font_size_enum(&mut self, value: FontSize) -> &mut Self {
668        self.add_property(font::font_size_enum(value))
669    }
670
671    /// Set the line-height property with LineHeight enum
672    pub fn line_height_enum(&mut self, value: LineHeight) -> &mut Self {
673        self.add_property(font::line_height_enum(value))
674    }
675
676    /// Set the text-decoration property
677    pub fn text_decoration(&mut self, value: TextDecoration) -> &mut Self {
678        self.add_property(font::text_decoration(value))
679    }
680
681    // Border properties
682
683    /// Set the border-style property
684    pub fn border_style(&mut self, value: BorderStyle) -> &mut Self {
685        self.add_property(border::border_style(value))
686    }
687
688    /// Set the border-radius property
689    pub fn border_radius(&mut self, value: Size) -> &mut Self {
690        self.add_property(border::border_radius(value))
691    }
692
693    /// Set the border property (shorthand)
694    pub fn border(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
695        self.add_property(border::border(width, style, color))
696    }
697
698    /// Set the border-top property (shorthand)
699    pub fn border_top(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
700        self.add_property(border::border_top(width, style, color))
701    }
702
703    /// Set the border-right property (shorthand)
704    pub fn border_right(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
705        self.add_property(border::border_right(width, style, color))
706    }
707
708    /// Set the border-bottom property (shorthand)
709    pub fn border_bottom(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
710        self.add_property(border::border_bottom(width, style, color))
711    }
712
713    /// Set the border-left property (shorthand)
714    pub fn border_left(&mut self, width: Size, style: BorderStyle, color: Color) -> &mut Self {
715        self.add_property(border::border_left(width, style, color))
716    }
717
718    /// Set the box-shadow property
719    pub fn box_shadow(&mut self, value: BoxShadow) -> &mut Self {
720        self.add_property(border::box_shadow(value))
721    }
722
723    /// Set the box-shadow property to none
724    pub fn box_shadow_none(&mut self) -> &mut Self {
725        self.add_property(border::box_shadow_none())
726    }
727
728    // Position properties
729
730    /// Set the top property
731    pub fn top(&mut self, value: Size) -> &mut Self {
732        self.add_property(position::top(value))
733    }
734
735    /// Set the right property
736    pub fn right(&mut self, value: Size) -> &mut Self {
737        self.add_property(position::right(value))
738    }
739
740    /// Set the bottom property
741    pub fn bottom(&mut self, value: Size) -> &mut Self {
742        self.add_property(position::bottom(value))
743    }
744
745    /// Set the left property
746    pub fn left(&mut self, value: Size) -> &mut Self {
747        self.add_property(position::left(value))
748    }
749
750    /// Set the z-index property
751    pub fn z_index(&mut self, value: ZIndex) -> &mut Self {
752        self.add_property(position::z_index(value))
753    }
754
755    // Layout properties
756
757    /// Set the overflow property
758    pub fn overflow(&mut self, value: Overflow) -> &mut Self {
759        self.add_property(layout::overflow(value))
760    }
761
762    /// Set the overflow-x property
763    pub fn overflow_x(&mut self, value: Overflow) -> &mut Self {
764        self.add_property(layout::overflow_x(value))
765    }
766
767    /// Set the overflow-y property
768    pub fn overflow_y(&mut self, value: Overflow) -> &mut Self {
769        self.add_property(layout::overflow_y(value))
770    }
771
772    /// Set the visibility property
773    pub fn visibility(&mut self, value: Visibility) -> &mut Self {
774        self.add_property(layout::visibility(value))
775    }
776
777    /// Set the opacity property
778    pub fn opacity(&mut self, value: f32) -> &mut Self {
779        self.add_property(layout::opacity(value))
780    }
781
782    /// Set the cursor property
783    pub fn cursor(&mut self, value: Cursor) -> &mut Self {
784        self.add_property(layout::cursor(value))
785    }
786
787    // Flex properties
788
789    /// Set the gap property
790    pub fn gap(&mut self, value: Size) -> &mut Self {
791        self.add_property(flex::gap(value))
792    }
793
794    /// Set the row-gap property
795    pub fn row_gap(&mut self, value: Size) -> &mut Self {
796        self.add_property(flex::row_gap(value))
797    }
798
799    /// Set the column-gap property
800    pub fn column_gap(&mut self, value: Size) -> &mut Self {
801        self.add_property(flex::column_gap(value))
802    }
803
804    // Grid properties
805
806    /// Set the grid-template-columns property
807    pub fn grid_template_columns(&mut self, value: &str) -> &mut Self {
808        self.add_property(grid::grid_template_columns(value))
809    }
810
811    /// Set the grid-template-rows property
812    pub fn grid_template_rows(&mut self, value: &str) -> &mut Self {
813        self.add_property(grid::grid_template_rows(value))
814    }
815
816    // Transition properties
817
818    /// Set the transition property
819    pub fn transition(&mut self, value: Transition) -> &mut Self {
820        self.add_property(transition::transition(value))
821    }
822
823    /// Set the transition property to none
824    pub fn transition_none(&mut self) -> &mut Self {
825        self.add_property(transition::transition_none())
826    }
827
828    /// Set the transition property to all
829    pub fn transition_all(&mut self, duration: f32, timing_function: Option<&str>, delay: Option<f32>) -> &mut Self {
830        self.add_property(transition::transition_all(duration, timing_function, delay))
831    }
832
833    // Size properties extension
834
835    /// Set the max-width property
836    pub fn max_width(&mut self, value: Size) -> &mut Self {
837        self.add_property(size_ext::max_width(value))
838    }
839
840    /// Set the min-width property
841    pub fn min_width(&mut self, value: Size) -> &mut Self {
842        self.add_property(size_ext::min_width(value))
843    }
844
845    /// Set the max-height property
846    pub fn max_height(&mut self, value: Size) -> &mut Self {
847        self.add_property(size_ext::max_height(value))
848    }
849
850    /// Set the min-height property
851    pub fn min_height(&mut self, value: Size) -> &mut Self {
852        self.add_property(size_ext::min_height(value))
853    }
854}
855
856impl fmt::Display for Style {
857    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
858        for (i, property) in self.properties.iter().enumerate() {
859            if i > 0 {
860                write!(f, " ")?;
861            }
862            write!(f, "{}", property)?;
863        }
864        Ok(())
865    }
866}
867
868/// Creates a new style builder for constructing CSS styles.
869///
870/// This function is the main entry point for the Mew CSS library. It returns a new
871/// `Style` instance that you can use to build CSS styles with a fluent API.
872///
873/// # Returns
874///
875/// A new, empty `Style` instance
876///
877/// # Examples
878///
879/// ```rust
880/// use mew_css::style;
881/// use mew_css::values::{Color, Size, Display};
882///
883/// let css = style()
884///     .color(Color::Blue)
885///     .background_color(Color::Rgb(240, 240, 240))
886///     .font_size(Size::Px(18))
887///     .display(Display::Block)
888///     .apply();
889///
890/// assert_eq!(css, "color: blue; background-color: rgb(240, 240, 240); font-size: 18px; display: block;");
891/// ```
892pub fn style() -> Style {
893    Style::new()
894}
895
896#[cfg(test)]
897mod tests {
898    use super::*;
899
900    #[test]
901    fn test_style_builder() {
902        let css = style()
903            .color(Color::White)
904            .background_color(Color::Rgba(255, 0, 0, 0.5))
905            .font_size(Size::Px(16))
906            .display(Display::Flex)
907            .apply();
908
909        assert_eq!(
910            css,
911            "color: white; background-color: rgba(255, 0, 0, 0.5); font-size: 16px; display: flex;"
912        );
913    }
914
915    #[test]
916    fn test_empty_style() {
917        let css = style().apply();
918        assert_eq!(css, "");
919    }
920
921    #[test]
922    fn test_multiple_properties() {
923        let css = style()
924            .width(Size::Percent(100.0))
925            .height(Size::Px(200))
926            .margin(Size::Auto)
927            .padding(Size::Px(10))
928            .apply();
929
930        assert_eq!(
931            css,
932            "width: 100%; height: 200px; margin: auto; padding: 10px;"
933        );
934    }
935}