1use crate::css::Css;
5use crate::data_type::{Color, Length, LengthPercentage};
6use crate::keyword::{Cursor, Overflow, PointerEvents, Visibility};
7
8impl Css {
9 pub fn opacity(self, v: f32) -> Self {
12 self.push_raw("opacity", crate::to_css::number_to_string(v))
13 }
14
15 pub fn visibility(self, v: Visibility) -> Self {
19 self.push("visibility", v)
20 }
21
22 pub fn overflow(self, v: Overflow) -> Self {
25 self.push("overflow-x", v).push("overflow-y", v)
26 }
27
28 pub fn overflow_x(self, v: Overflow) -> Self {
31 self.push("overflow-x", v)
32 }
33
34 pub fn overflow_y(self, v: Overflow) -> Self {
37 self.push("overflow-y", v)
38 }
39
40 pub fn cursor(self, v: Cursor) -> Self {
43 self.push("cursor", v)
44 }
45
46 pub fn pointer_events(self, v: PointerEvents) -> Self {
49 self.push("pointer-events", v)
50 }
51
52 pub fn box_shadow(
56 self,
57 offset_x: Length,
58 offset_y: Length,
59 blur_radius: Length,
60 spread_radius: Length,
61 color: Color,
62 ) -> Self {
63 use crate::to_css::ToCss;
64 let mut s = String::new();
65 let _ = offset_x.to_css(&mut s);
66 s.push(' ');
67 let _ = offset_y.to_css(&mut s);
68 s.push(' ');
69 let _ = blur_radius.to_css(&mut s);
70 s.push(' ');
71 let _ = spread_radius.to_css(&mut s);
72 s.push(' ');
73 let _ = color.to_css(&mut s);
74 self.push_raw("box-shadow", s)
75 }
76
77 pub fn box_shadow_inset(
80 self,
81 offset_x: Length,
82 offset_y: Length,
83 blur_radius: Length,
84 spread_radius: Length,
85 color: Color,
86 ) -> Self {
87 use crate::to_css::ToCss;
88 let mut s = String::from("inset ");
89 let _ = offset_x.to_css(&mut s);
90 s.push(' ');
91 let _ = offset_y.to_css(&mut s);
92 s.push(' ');
93 let _ = blur_radius.to_css(&mut s);
94 s.push(' ');
95 let _ = spread_radius.to_css(&mut s);
96 s.push(' ');
97 let _ = color.to_css(&mut s);
98 self.push_raw("box-shadow", s)
99 }
100
101 pub fn filter(self, value: impl Into<String>) -> Self {
106 self.push_raw("filter", value)
107 }
108
109 pub fn mask_image(self, value: impl Into<String>) -> Self {
112 self.push_raw("mask-image", value)
113 }
114
115 pub fn clip_path(self, value: impl Into<String>) -> Self {
118 self.push_raw("clip-path", value)
119 }
120
121 pub fn caret_color(self, v: Color) -> Self {
124 self.push("caret-color", v)
125 }
126
127 pub fn outline_width(self, v: Length) -> Self {
130 self.push("outline-width", v)
131 }
132
133 pub fn outline_color(self, v: Color) -> Self {
136 self.push("outline-color", v)
137 }
138
139 pub fn outline_style(self, v: crate::keyword::BorderStyle) -> Self {
142 self.push("outline-style", v)
143 }
144
145 pub fn outline_offset(self, v: Length) -> Self {
148 self.push("outline-offset", v)
149 }
150
151 pub fn caret_width(self, v: Length) -> Self {
154 self.push("caret-width", v)
155 }
156
157 pub fn x_handle_color(self, v: Color) -> Self {
160 self.push("-x-handle-color", v)
161 }
162
163 pub fn x_handle_size(self, v: impl Into<LengthPercentage>) -> Self {
166 self.push("-x-handle-size", v.into())
167 }
168
169 pub fn x_auto_font_size(self, enabled: bool) -> Self {
172 self.push_raw("-x-auto-font-size", if enabled { "true" } else { "false" })
173 }
174
175 pub fn x_auto_font_size_preset_sizes(self, sizes: impl IntoIterator<Item = Length>) -> Self {
178 use crate::to_css::ToCss;
179 let mut s = String::new();
180 let mut first = true;
181 for sz in sizes {
182 if !first {
183 s.push(' ');
184 }
185 let _ = sz.to_css(&mut s);
186 first = false;
187 }
188 self.push_raw("-x-auto-font-size-preset-sizes", s)
189 }
190}
191
192#[cfg(test)]
193mod tests {
194 use crate::data_type::Color;
195 use crate::ext::*;
196 use crate::keyword::*;
197 use crate::Css;
198
199 #[test]
200 fn opacity_full_range() {
201 assert_eq!(Css::new().opacity(0.0).to_string(), "opacity: 0;");
202 assert_eq!(Css::new().opacity(0.5).to_string(), "opacity: 0.5;");
203 assert_eq!(Css::new().opacity(1.0).to_string(), "opacity: 1;");
204 }
205
206 #[test]
207 fn visibility_keyword() {
208 assert_eq!(
209 Css::new().visibility(Visibility::Hidden).to_string(),
210 "visibility: hidden;"
211 );
212 }
213
214 #[test]
215 fn overflow_expands_to_both_axes() {
216 let s = Css::new().overflow(Overflow::Hidden);
217 assert_eq!(s.to_string(), "overflow-x: hidden; overflow-y: hidden;");
218 }
219
220 #[test]
221 fn overflow_axis_individual_override() {
222 let s = Css::new()
223 .overflow(Overflow::Hidden)
224 .overflow_y(Overflow::Visible);
225 assert_eq!(s.to_string(), "overflow-x: hidden; overflow-y: visible;");
226 }
227
228 #[test]
229 fn cursor_and_pointer_events() {
230 let s = Css::new()
231 .cursor(Cursor::Pointer)
232 .pointer_events(PointerEvents::None);
233 assert_eq!(s.to_string(), "cursor: pointer; pointer-events: none;");
234 }
235
236 #[test]
237 fn box_shadow_outer() {
238 let s = Css::new().box_shadow(
239 2.px(),
240 4.px(),
241 8.px(),
242 crate::data_type::Length::Zero,
243 Color::hex(0x000000),
244 );
245 assert_eq!(s.to_string(), "box-shadow: 2px 4px 8px 0 rgb(0, 0, 0);");
246 }
247
248 #[test]
249 fn box_shadow_inset() {
250 let s = Css::new().box_shadow_inset(
251 crate::data_type::Length::Zero,
252 crate::data_type::Length::Zero,
253 4.px(),
254 crate::data_type::Length::Zero,
255 Color::hex(0xFFFFFF),
256 );
257 assert_eq!(
258 s.to_string(),
259 "box-shadow: inset 0 0 4px 0 rgb(255, 255, 255);"
260 );
261 }
262
263 #[test]
264 fn filter_clip_path_mask_raw() {
265 let s = Css::new()
266 .filter("blur(4px)")
267 .clip_path("circle(50%)")
268 .mask_image("url(\"a.png\")");
269 assert_eq!(
270 s.to_string(),
271 "filter: blur(4px); clip-path: circle(50%); mask-image: url(\"a.png\");"
272 );
273 }
274
275 #[test]
276 fn outline_props() {
277 let s = Css::new()
278 .outline_width(1.px())
279 .outline_style(BorderStyle::Solid)
280 .outline_color(Color::hex(0xFF0000))
281 .outline_offset(2.px());
282 assert_eq!(
283 s.to_string(),
284 "outline-width: 1px; outline-style: solid; outline-color: rgb(255, 0, 0); outline-offset: 2px;"
285 );
286 }
287
288 #[test]
289 fn caret_props() {
290 let s = Css::new()
291 .caret_color(Color::hex(0xFF00FF))
292 .caret_width(2.px());
293 assert_eq!(
294 s.to_string(),
295 "caret-color: rgb(255, 0, 255); caret-width: 2px;"
296 );
297 }
298
299 #[test]
300 fn x_handle_props() {
301 let s = Css::new()
302 .x_handle_color(Color::hex(0x00FF00))
303 .x_handle_size(8.px());
304 assert_eq!(
305 s.to_string(),
306 "-x-handle-color: rgb(0, 255, 0); -x-handle-size: 8px;"
307 );
308 }
309
310 #[test]
311 fn x_auto_font_size_flag_and_presets() {
312 let s = Css::new()
313 .x_auto_font_size(true)
314 .x_auto_font_size_preset_sizes([12.px(), 14.px(), 16.px()]);
315 assert_eq!(
316 s.to_string(),
317 "-x-auto-font-size: true; -x-auto-font-size-preset-sizes: 12px 14px 16px;"
318 );
319 }
320}