1use crate::{append_property::AppendProperty, prelude::*, Property};
2
3crate::macros::easy_enum! {border-collapse separate collapse}
4crate::macros::easy_enum! {box-decoration-break slice clone}
5crate::macros::easy_enum! {outline-width medium thin thick [unit]}
6crate::macros::easy_enum! {outline-style none hidden dotted dashed solid double groove ridge inset outset}
7crate::macros::easy_enum! {border-image-slice fill [raw]} crate::macros::easy_enum! {border-image-width auto [raw]} crate::macros::easy_enum! {border-image-outset [raw]} crate::macros::easy_enum! {border-image-repeat stretch repeat round space}
11crate::macros::easy_color! {outline-color}
12
13#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
14pub enum BorderImageSource {
15 None,
16 Initial,
17 Inherit,
18 Unset,
19 Some(Vec<crate::Image>),
20}
21
22impl std::fmt::Display for BorderImageSource {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 Self::None => "border-image-source:none;".fmt(f),
26 Self::Initial => "border-image-source:initial;".fmt(f),
27 Self::Inherit => "border-image-source:inherit;".fmt(f),
28 Self::Unset => "border-image-source:unset;".fmt(f),
29 Self::Some(images) => {
30 "border-image-source:".fmt(f)?;
31 if let Some((first, rest)) = images.split_first() {
32 write!(f, "{}", first)?;
33 for image in rest {
34 write!(f, ",{}", image)?;
35 }
36 }
37 ";".fmt(f)
38 },
39 }
40 }
41}
42
43#[rustfmt::skip]
44#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, strum::Display, PartialOrd, Ord)]
45pub enum BorderStyle {
46 #[strum(to_string = "none")] None,
47 #[strum(to_string = "hidden")] Hidden,
48 #[strum(to_string = "dotted")] Dotted,
49 #[strum(to_string = "dashed")] Dashed,
50 #[strum(to_string = "solid")] Solid,
51 #[strum(to_string = "double")] Double,
52 #[strum(to_string = "groove")] Groove,
53 #[strum(to_string = "ridge")] Ridge,
54 #[strum(to_string = "inset")] Inset,
55 #[strum(to_string = "outset")] Outset,
56 #[strum(to_string = "initial")] Initial,
57 #[strum(to_string = "inherit")] Inherit,
58 #[strum(to_string = "unset")] Unset,
59}
60
61#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
62pub enum BorderWidth {
63 Medium,
64 Thin,
65 Thick,
66 Some(crate::Unit),
67 Initial,
68 Inherit,
69 Unset,
70}
71
72#[rustfmt::skip]
73impl std::fmt::Display for BorderWidth {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 match self {
76 Self::Medium => "medium".fmt(f),
77 Self::Thin => "thin".fmt(f),
78 Self::Thick => "thick".fmt(f),
79 Self::Some(x) => x.fmt(f),
80 Self::Initial => "initial".fmt(f),
81 Self::Inherit => "inherit".fmt(f),
82 Self::Unset => "unset".fmt(f),
83 }
84 }
85}
86
87#[derive(Debug, PartialEq, Eq, Hash, Clone, Default, PartialOrd, Ord)]
88pub struct BoxShadowEffect {
89 pub inset: bool,
90 pub offset_x: Unit,
91 pub offset_y: Unit,
92 pub blur_radius: Unit,
93 pub spread_radius: Unit,
94 pub color: crate::Color,
95}
96
97impl std::fmt::Display for BoxShadowEffect {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 if self.inset { "inset ".fmt(f)? }
100 write!(f, "{} {} {} {} {}", self.offset_x, self.offset_y, self.blur_radius, self.spread_radius, self.color)
101 }
102}
103
104impl AppendProperty for BoxShadowEffect {
105 fn append_property(self, props: &mut Vec<Property>) { BoxShadow::Some(vec![self]).append_property(props) }
106}
107
108#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
109pub enum BoxShadow {
110 None,
111 Initial,
112 Inherit,
113 Unset,
114 Some(Vec<BoxShadowEffect>),
115}
116
117impl std::fmt::Display for BoxShadow {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 match self {
120 Self::None => "box-shadow:none;".fmt(f),
121 Self::Initial => "box-shadow:initial;".fmt(f),
122 Self::Inherit => "box-shadow:inherit;".fmt(f),
123 Self::Unset => "box-shadow:unset;".fmt(f),
124 Self::Some(effects) => {
125 "box-shadow:".fmt(f)?;
126 if let Some((first, rest)) = effects.split_first() {
127 write!(f, "{}", first)?;
128 for effect in rest {
129 write!(f, ",{}", effect)?;
130 }
131 }
132 ";".fmt(f)
133 },
134 }
135 }
136}
137
138#[rustfmt::skip]
139#[macro_export]
140#[doc(hidden)]
141macro_rules! __border_width {
142 ($side:ident, medium) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Medium)}};
143 ($side:ident, thin) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Thin)}};
144 ($side:ident, thick) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Thick)}};
145 ($side:ident, initial) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Initial)}};
146 ($side:ident, inherit) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Inherit)}};
147 ($side:ident, unset) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Unset)}};
148 ($side:ident, $($val:tt)+) => {$crate::paste::item!{$crate::Property::[<Border $side Width>]($crate::BorderWidth::Some($crate::unit!($($val)+)))}};
149}
150
151#[macro_export] macro_rules! border_left_width {($($tt:tt)+) => {$crate::__border_width!(Left, $($tt)+)}}
152#[macro_export] macro_rules! border_right_width {($($tt:tt)+) => {$crate::__border_width!(Right, $($tt)+)}}
153#[macro_export] macro_rules! border_top_width {($($tt:tt)+) => {$crate::__border_width!(Top, $($tt)+)}}
154#[macro_export] macro_rules! border_bottom_width {($($tt:tt)+) => {$crate::__border_width!(Bottom, $($tt)+)}}
155#[macro_export] macro_rules! border_width {($($tt:tt)+) => {
156 vec![
157 $crate::border_left_width!($($tt)+),
158 $crate::border_right_width!($($tt)+),
159 $crate::border_top_width!($($tt)+),
160 $crate::border_bottom_width!($($tt)+),
161 ]
162}}
163
164#[rustfmt::skip]
165#[macro_export]
166#[doc(hidden)]
167macro_rules! __border_style {
168 ($side:ident, none) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::None)}};
169 ($side:ident, hidden) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Hidden)}};
170 ($side:ident, dotted) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Dotted)}};
171 ($side:ident, dashed) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Dashed)}};
172 ($side:ident, solid) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Solid)}};
173 ($side:ident, double) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Double)}};
174 ($side:ident, groove) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Groove)}};
175 ($side:ident, ridge) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Ridge)}};
176 ($side:ident, inset) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Inset)}};
177 ($side:ident, outset) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Outset)}};
178 ($side:ident, initial) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Initial)}};
179 ($side:ident, inherit) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Inherit)}};
180 ($side:ident, unset) => {$crate::paste::item!{$crate::Property::[<Border $side Style>]($crate::BorderStyle::Unset)}};
181}
182
183#[macro_export] macro_rules! border_left_style {($($tt:tt)+) => {$crate::__border_style!(Left, $($tt)+)}}
184#[macro_export] macro_rules! border_right_style {($($tt:tt)+) => {$crate::__border_style!(Right, $($tt)+)}}
185#[macro_export] macro_rules! border_top_style {($($tt:tt)+) => {$crate::__border_style!(Top, $($tt)+)}}
186#[macro_export] macro_rules! border_bottom_style {($($tt:tt)+) => {$crate::__border_style!(Bottom, $($tt)+)}}
187#[macro_export] macro_rules! border_style {($($tt:tt)+) => {
188 vec![
189 $crate::border_left_style!($($tt)+),
190 $crate::border_right_style!($($tt)+),
191 $crate::border_top_style!($($tt)+),
192 $crate::border_bottom_style!($($tt)+),
193 ]
194}}
195
196crate::macros::easy_color! {border_left_color}
197crate::macros::easy_color! {border_right_color}
198crate::macros::easy_color! {border_top_color}
199crate::macros::easy_color! {border_bottom_color}
200#[macro_export] macro_rules! border_color {($($tt:tt)+) => {
201 vec![
202 $crate::border_left_color!($($tt)+),
203 $crate::border_right_color!($($tt)+),
204 $crate::border_top_color!($($tt)+),
205 $crate::border_bottom_color!($($tt)+),
206 ]
207}}
208
209crate::macros::unit_value_macro! {border_top_left_radius BorderTopLeftRadius}
210crate::macros::unit_value_macro! {border_top_right_radius BorderTopRightRadius}
211crate::macros::unit_value_macro! {border_bottom_left_radius BorderBottomLeftRadius}
212crate::macros::unit_value_macro! {border_bottom_right_radius BorderBottomRightRadius}
213#[macro_export] macro_rules! border_radius {($($tt:tt)+) => {
214 vec![
215 $crate::border_top_left_radius!($($tt)+),
216 $crate::border_top_right_radius!($($tt)+),
217 $crate::border_bottom_left_radius!($($tt)+),
218 $crate::border_bottom_right_radius!($($tt)+),
219 ]
220}}
221
222#[test]
223fn border_width_values() {
224 assert_eq!(__border_width!(Left, medium).to_string(), "border-left-width:medium;");
225 assert_eq!(__border_width!(Left, thin).to_string(), "border-left-width:thin;");
226 assert_eq!(__border_width!(Left, thick).to_string(), "border-left-width:thick;");
227 assert_eq!(__border_width!(Left, initial).to_string(), "border-left-width:initial;");
228 assert_eq!(__border_width!(Left, inherit).to_string(), "border-left-width:inherit;");
229 assert_eq!(__border_width!(Left, unset).to_string(), "border-left-width:unset;");
230
231 assert_eq!(__border_width!(Right, medium).to_string(), "border-right-width:medium;");
232 assert_eq!(__border_width!(Right, thin).to_string(), "border-right-width:thin;");
233 assert_eq!(__border_width!(Right, thick).to_string(), "border-right-width:thick;");
234 assert_eq!(__border_width!(Right, initial).to_string(), "border-right-width:initial;");
235 assert_eq!(__border_width!(Right, inherit).to_string(), "border-right-width:inherit;");
236 assert_eq!(__border_width!(Right, unset).to_string(), "border-right-width:unset;");
237
238 assert_eq!(__border_width!(Top, medium).to_string(), "border-top-width:medium;");
239 assert_eq!(__border_width!(Top, thin).to_string(), "border-top-width:thin;");
240 assert_eq!(__border_width!(Top, thick).to_string(), "border-top-width:thick;");
241 assert_eq!(__border_width!(Top, initial).to_string(), "border-top-width:initial;");
242 assert_eq!(__border_width!(Top, inherit).to_string(), "border-top-width:inherit;");
243 assert_eq!(__border_width!(Top, unset).to_string(), "border-top-width:unset;");
244
245 assert_eq!(__border_width!(Bottom, medium).to_string(), "border-bottom-width:medium;");
246 assert_eq!(__border_width!(Bottom, thin).to_string(), "border-bottom-width:thin;");
247 assert_eq!(__border_width!(Bottom, thick).to_string(), "border-bottom-width:thick;");
248 assert_eq!(__border_width!(Bottom, initial).to_string(), "border-bottom-width:initial;");
249 assert_eq!(__border_width!(Bottom, inherit).to_string(), "border-bottom-width:inherit;");
250 assert_eq!(__border_width!(Bottom, unset).to_string(), "border-bottom-width:unset;");
251}
252
253#[test]
254fn border_style_values() {
255 assert_eq!(__border_style!(Left, none).to_string(), "border-left-style:none;");
256 assert_eq!(__border_style!(Left, hidden).to_string(), "border-left-style:hidden;");
257 assert_eq!(__border_style!(Left, dotted).to_string(), "border-left-style:dotted;");
258 assert_eq!(__border_style!(Left, dashed).to_string(), "border-left-style:dashed;");
259 assert_eq!(__border_style!(Left, solid).to_string(), "border-left-style:solid;");
260 assert_eq!(__border_style!(Left, double).to_string(), "border-left-style:double;");
261 assert_eq!(__border_style!(Left, groove).to_string(), "border-left-style:groove;");
262 assert_eq!(__border_style!(Left, ridge).to_string(), "border-left-style:ridge;");
263 assert_eq!(__border_style!(Left, inset).to_string(), "border-left-style:inset;");
264 assert_eq!(__border_style!(Left, outset).to_string(), "border-left-style:outset;");
265 assert_eq!(__border_style!(Left, initial).to_string(), "border-left-style:initial;");
266 assert_eq!(__border_style!(Left, inherit).to_string(), "border-left-style:inherit;");
267 assert_eq!(__border_style!(Left, unset).to_string(), "border-left-style:unset;");
268
269 assert_eq!(__border_style!(Right, none).to_string(), "border-right-style:none;");
270 assert_eq!(__border_style!(Right, hidden).to_string(), "border-right-style:hidden;");
271 assert_eq!(__border_style!(Right, dotted).to_string(), "border-right-style:dotted;");
272 assert_eq!(__border_style!(Right, dashed).to_string(), "border-right-style:dashed;");
273 assert_eq!(__border_style!(Right, solid).to_string(), "border-right-style:solid;");
274 assert_eq!(__border_style!(Right, double).to_string(), "border-right-style:double;");
275 assert_eq!(__border_style!(Right, groove).to_string(), "border-right-style:groove;");
276 assert_eq!(__border_style!(Right, ridge).to_string(), "border-right-style:ridge;");
277 assert_eq!(__border_style!(Right, inset).to_string(), "border-right-style:inset;");
278 assert_eq!(__border_style!(Right, outset).to_string(), "border-right-style:outset;");
279 assert_eq!(__border_style!(Right, initial).to_string(), "border-right-style:initial;");
280 assert_eq!(__border_style!(Right, inherit).to_string(), "border-right-style:inherit;");
281 assert_eq!(__border_style!(Right, unset).to_string(), "border-right-style:unset;");
282
283 assert_eq!(__border_style!(Top, none).to_string(), "border-top-style:none;");
284 assert_eq!(__border_style!(Top, hidden).to_string(), "border-top-style:hidden;");
285 assert_eq!(__border_style!(Top, dotted).to_string(), "border-top-style:dotted;");
286 assert_eq!(__border_style!(Top, dashed).to_string(), "border-top-style:dashed;");
287 assert_eq!(__border_style!(Top, solid).to_string(), "border-top-style:solid;");
288 assert_eq!(__border_style!(Top, double).to_string(), "border-top-style:double;");
289 assert_eq!(__border_style!(Top, groove).to_string(), "border-top-style:groove;");
290 assert_eq!(__border_style!(Top, ridge).to_string(), "border-top-style:ridge;");
291 assert_eq!(__border_style!(Top, inset).to_string(), "border-top-style:inset;");
292 assert_eq!(__border_style!(Top, outset).to_string(), "border-top-style:outset;");
293 assert_eq!(__border_style!(Top, initial).to_string(), "border-top-style:initial;");
294 assert_eq!(__border_style!(Top, inherit).to_string(), "border-top-style:inherit;");
295 assert_eq!(__border_style!(Top, unset).to_string(), "border-top-style:unset;");
296
297 assert_eq!(__border_style!(Bottom, none).to_string(), "border-bottom-style:none;");
298 assert_eq!(__border_style!(Bottom, hidden).to_string(), "border-bottom-style:hidden;");
299 assert_eq!(__border_style!(Bottom, dotted).to_string(), "border-bottom-style:dotted;");
300 assert_eq!(__border_style!(Bottom, dashed).to_string(), "border-bottom-style:dashed;");
301 assert_eq!(__border_style!(Bottom, solid).to_string(), "border-bottom-style:solid;");
302 assert_eq!(__border_style!(Bottom, double).to_string(), "border-bottom-style:double;");
303 assert_eq!(__border_style!(Bottom, groove).to_string(), "border-bottom-style:groove;");
304 assert_eq!(__border_style!(Bottom, ridge).to_string(), "border-bottom-style:ridge;");
305 assert_eq!(__border_style!(Bottom, inset).to_string(), "border-bottom-style:inset;");
306 assert_eq!(__border_style!(Bottom, outset).to_string(), "border-bottom-style:outset;");
307 assert_eq!(__border_style!(Bottom, initial).to_string(), "border-bottom-style:initial;");
308 assert_eq!(__border_style!(Bottom, inherit).to_string(), "border-bottom-style:inherit;");
309 assert_eq!(__border_style!(Bottom, unset).to_string(), "border-bottom-style:unset;");
310}