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}