1#[macro_use] mod flex;
2#[macro_use] mod margin;
3#[macro_use] mod padding;
4#[macro_use] mod dimensions;
5#[macro_use] mod position;
6#[macro_use] mod text;
7#[macro_use] mod border;
8#[macro_use] mod background;
9#[macro_use] mod svg;
10#[macro_use] mod animation;
11#[macro_use] mod transform;
12#[macro_use] mod filter;
13#[macro_use] mod grid;
14#[macro_use] mod clip_path;
15#[macro_use] mod appearance;
16
17use crate::prelude::*;
18pub use animation::*;
19pub use appearance::*;
20pub use background::*;
21pub use border::*;
22pub use clip_path::*;
23pub use dimensions::*;
24pub use filter::*;
25pub use flex::*;
26pub use grid::*;
27pub use margin::*;
28pub use padding::*;
29pub use position::*;
30pub use svg::*;
31pub use text::*;
32pub use transform::*;
33
34#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
35pub enum ColorValue {
36 Rgba(crate::color::Color),
37 Initial,
38 Inherit,
39 Unset,
40}
41
42#[rustfmt::skip]
43impl std::fmt::Display for ColorValue {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 match self {
46 Self::Rgba(x) => x.fmt(f),
47 Self::Initial => "initial".fmt(f),
48 Self::Inherit => "inherit".fmt(f),
49 Self::Unset => "unset".fmt(f),
50 }
51 }
52}
53
54#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
55pub enum UnitValue {
56 Unit(Unit),
57 Initial,
58 Inherit,
59 Unset,
60}
61
62#[rustfmt::skip]
63impl std::fmt::Display for UnitValue {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 match self {
66 Self::Unit(x) => x.fmt(f),
67 Self::Initial => "initial".fmt(f),
68 Self::Inherit => "inherit".fmt(f),
69 Self::Unset => "unset".fmt(f),
70 }
71 }
72}
73
74#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
89pub struct LinearGradient {
90 pub angle: F32,
91 pub stop_list: Vec<(crate::Color, Unit)>,
92}
93
94impl std::fmt::Display for LinearGradient {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "{}deg", self.angle)?;
97 for (color, stop) in &self.stop_list {
98 write!(f, ",{} {}", color, stop)?;
99 }
100 Ok(())
101 }
102}
103
104#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
105pub enum Image {
106 Url(String),
107 LinearGradient(LinearGradient),
108 RepeatingLinearGradient(LinearGradient),
109 }
113
114impl Image {
115 pub fn url(x: impl Into<String>) -> Self { Self::Url(x.into()) }
116 pub fn linear_gradient(angle: f32, stop_list: Vec<(crate::Color, Unit)>) -> Self { Self::LinearGradient(LinearGradient { angle: F32::new(angle).unwrap(), stop_list }) }
117 pub fn repeating_linear_gradient(angle: f32, stop_list: Vec<(crate::Color, Unit)>) -> Self { Self::RepeatingLinearGradient(LinearGradient { angle: F32::new(angle).unwrap(), stop_list }) }
118}
119
120impl std::fmt::Display for Image {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 match self {
123 Self::Url(x) => write!(f, r#"url("{}")"#, x),
124 Self::LinearGradient(x) => write!(f, "linear-gradient({})", x),
125 Self::RepeatingLinearGradient(x) => write!(f, "repeating-linear-gradient({})", x),
126 }
127 }
128}
129
130#[derive(Debug, PartialEq, Eq, Hash, Clone, PartialOrd, Ord)]
131pub enum BasicShape {
132 Polygon(Vec<(Unit, Unit)>),
133 }
135
136impl std::fmt::Display for BasicShape {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 match self {
139 Self::Polygon(points) => {
140 "polygon(".fmt(f)?;
141 if let Some(((x, y), rest)) = points.split_first() {
142 write!(f, "{} {}", x, y)?;
143 for (x, y) in rest {
144 write!(f, ",{} {}", x, y)?;
145 }
146 }
147 ")".fmt(f)
148 },
149 }
150 }
151}
152
153macro_rules! generate_properties {
154 (
155 stutter => ($($stutter_name:ident),*$(,)?),
156 named => ($($css_name:expr => $named_name:ident($named_type:ty)),*$(,)?),
157 ) => {
158 pub use Property::{$($named_name),*};
159
160 #[allow(clippy::derive_ord_xor_partial_ord)]
161 #[derive(Debug, PartialEq, Eq, Hash, Clone, strum::EnumDiscriminants, Ord)]
162 #[strum_discriminants(derive(PartialOrd))]
163 pub enum Property {
164 Raw(String),
165 $($stutter_name($stutter_name),)*
166 $($named_name($named_type)),*
167 }
168
169 impl std::cmp::PartialOrd for Property {
170 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
171 PropertyDiscriminants::from(self).partial_cmp(&PropertyDiscriminants::from(other))
172 }
173 }
174
175 impl std::fmt::Display for Property {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 match self {
178 Self::Raw(x) => x.fmt(f),
179 $(Self::$named_name(x) => write!(f, "{}:{};", $css_name, x),)*
180 $(Self::$stutter_name(x) => x.fmt(f)),*
181 }
182 }
183 }
184
185 $(
186 impl From<$stutter_name> for Property {
187 fn from(x: $stutter_name) -> Self { Self::$stutter_name(x) }
188 }
189
190 impl crate::AppendProperty for $stutter_name {
191 fn append_property(self, decls: &mut Vec<Property>) { decls.push(Property::$stutter_name(self)); }
192 }
193 )*
194 };
195}
196
197generate_properties! {
199 stutter => (
202 FlexWrap, FlexDirection,
203 JustifyContent, AlignItems, AlignContent, AlignSelf,
204 JustifyItems, JustifySelf,
205 FlexBasis, FlexGrow, FlexShrink,
206
207 Order,
208 Position,
209 Display,
210 BoxSizing,
211 Visibility,
212 ZIndex,
213 OverflowX, OverflowY,
214 Direction,
215 UnicodeBidi,
216 WhiteSpace,
217 WritingMode,
218 HangingPunctuation,
219 Hyphens,
220 TextAlign,
221 TextAlignLast,
222 TextJustify,
223 FontStretch,
224 UserSelect,
225 ScrollBehavior,
226 PointerEvents,
227 TouchAction,
228 Resize,
229 ObjectFit,
230 ListStyleType, ListStyleImage, ListStylePosition,
231
232 BreakAfter, BreakBefore, BreakInside,
233
234 FontVariant,
235 WordBreak,
236 WordWrap,
237 FontStyle,
238 TransformStyle,
239 BackgroundBlendMode,
240 MixBlendMode,
241 Isolation,
242 CaptionSide,
243 EmptyCells,
244 TableLayout,
245 BorderCollapse,
246 All,
247 FontWeight,
248 FontSize,
249 BackgroundRepeat,
250 BackgroundAttachment,
251 Cursor,
252 TextTransform,
253 TextShadow,
254 FontKerning,
255 FontFamily,
256 WordSpacing,
257 TextOverflow,
258 VerticalAlign,
259 LineHeight,
260 LetterSpacing,
261 TabSize,
262 BoxDecorationBreak,
263 OutlineWidth,
264 OutlineStyle,
265 Content,
266 Opacity,
267 Perspective,
268 BackfaceVisibility,
269 TextDecorationStyle,
270 TextDecorationLine,
271 TextRendering,
272 VectorEffect,
273 AlignmentBaseline,
274 DominantBaseline,
275 TextAnchor,
276 StrokeLinecap,
277 BackgroundImage,
278 BackgroundSize,
279
280 AnimationDirection, AnimationFillMode, AnimationIterationCount,
281 AnimationName, AnimationPlayState, AnimationTimingFunction,
282 AnimationDuration, AnimationDelay,
283
284 TransitionProperty, TransitionTimingFunction,
285 TransitionDuration, TransitionDelay,
286
287 Transform,
288 Filter,
289
290 BorderImageSource, BorderImageSlice, BorderImageWidth,
291 BorderImageOutset, BorderImageRepeat,
292
293 ClipPath,
294 BackgroundOrigin,
295 BackgroundClip,
296 GridAutoFlow,
297 RowGap,
298 ColumnGap,
299 GridGap,
300 OverflowWrap,
301 BoxShadow,
302 TransformOrigin,
303 Appearance,
304 MaskImage,
305 MaskSize,
306 Float,
307 Clear,
308 AspectRatio,
309 OverflowAnchor,
310 ),
311 named => (
313 "margin-left" => MarginLeft(Margin),
314 "margin-right" => MarginRight(Margin),
315 "margin-top" => MarginTop(Margin),
316 "margin-bottom" => MarginBottom(Margin),
317
318 "padding-left" => PaddingLeft(UnitValue),
319 "padding-right" => PaddingRight(UnitValue),
320 "padding-top" => PaddingTop(UnitValue),
321 "padding-bottom" => PaddingBottom(UnitValue),
322
323 "width" => Width(DimensionExtremity),
324 "height" => Height(DimensionExtremity),
325 "min-width" => MinWidth(DimensionExtremity),
326 "max-width" => MaxWidth(DimensionExtremity),
327 "min-height" => MinHeight(DimensionExtremity),
328 "max-height" => MaxHeight(DimensionExtremity),
329
330 "top" => Top(Dimension),
331 "right" => Right(Dimension),
332 "left" => Left(Dimension),
333 "bottom" => Bottom(Dimension),
334
335 "border-left-color" => BorderLeftColor(ColorValue),
336 "border-right-color" => BorderRightColor(ColorValue),
337 "border-top-color" => BorderTopColor(ColorValue),
338 "border-bottom-color" => BorderBottomColor(ColorValue),
339
340 "border-left-style" => BorderLeftStyle(BorderStyle),
341 "border-right-style" => BorderRightStyle(BorderStyle),
342 "border-top-style" => BorderTopStyle(BorderStyle),
343 "border-bottom-style" => BorderBottomStyle(BorderStyle),
344
345 "border-left-width" => BorderLeftWidth(BorderWidth),
346 "border-right-width" => BorderRightWidth(BorderWidth),
347 "border-top-width" => BorderTopWidth(BorderWidth),
348 "border-bottom-width" => BorderBottomWidth(BorderWidth),
349
350 "border-top-left-radius" => BorderTopLeftRadius(UnitValue),
351 "border-top-right-radius" => BorderTopRightRadius(UnitValue),
352 "border-bottom-left-radius" => BorderBottomLeftRadius(UnitValue),
353 "border-bottom-right-radius" => BorderBottomRightRadius(UnitValue),
354
355 "background-color" => BackgroundColor(ColorValue),
356 "color" => Color(ColorValue),
357 "text-decoration-color" => TextDecorationColor(ColorValue),
358 "fill" => Fill(ColorValue),
359 "stroke" => Stroke(ColorValue),
360 "stroke-width" => StrokeWidth(UnitValue),
361 "outline-color" => OutlineColor(ColorValue),
362
363 "grid-template-columns" => GridTemplateColumns(GridTemplate),
364 "grid-template-rows" => GridTemplateRows(GridTemplate),
365 "grid-auto-columns" => GridAutoColumns(GridAuto),
366 "grid-auto-rows" => GridAutoRows(GridAuto),
367
368 "text-indent" => TextIndent(UnitValue),
369 "outline-offset" => OutlineOffset(UnitValue),
370
371 "grid-column-start" => GridColumnStart(GridSpan),
372 "grid-column-end" => GridColumnEnd(GridSpan),
373 "grid-row-start" => GridRowStart(GridSpan),
374 "grid-row-end" => GridRowEnd(GridSpan),
375
376 "background-position-x" => BackgroundPositionX(UnitValue),
377 "background-position-y" => BackgroundPositionY(UnitValue),
378 ),
379}
380
381crate::macros::easy_enum! {box-sizing content-box border-box}
382crate::macros::easy_enum! {visibility visible hidden collapse}
383crate::macros::easy_enum! {display block none inline inline-block flex inline-flex grid inline-grid flow-root contents table table-row table-row-group table-header-group table-footer-group table-cell table-column-group table-column table-caption list-item}
384crate::macros::easy_enum! {scroll-behavior auto smooth}
386crate::macros::easy_enum! {pointer-events auto none}
387crate::macros::easy_enum! {touch-action auto none manipulation}
388crate::macros::easy_enum! {resize none both horizontal vertical}
389crate::macros::easy_enum! {object-fit fill contain cover scale-down none}
390crate::macros::easy_enum! {transform-style flat preserve-3d}
391crate::macros::easy_enum! {background-blend-mode normal multiply screen overlay darken lighten color-dodge saturation color luminosity}
392crate::macros::easy_enum! {mix-blend-mode normal multiply screen overlay darken lighten color-dodge color-burn difference exclusion hue saturation color luminosity}
393crate::macros::easy_enum! {isolation auto isolate}
394crate::macros::easy_enum! {caption-side top bottom}
395crate::macros::easy_enum! {empty-cells show hide}
396crate::macros::easy_enum! {table-layout auto fixed}
397crate::macros::easy_enum! {all}
398crate::macros::easy_enum! {cursor auto alias all-scroll cell context-menu col-resize copy crosshair default e-resize ew-resize grab grabbing help move n-resize ne-resize nesw-resize ns-resize nw-resize nwse-resize no-drop none not-allowed pointer progress row-resize s-resize se-resize sw-resize text vertical-text w-resize wait zoom-in zoom-out}
399crate::macros::easy_enum! {content normal none counter open-quote close-quote no-open-quote no-close-quote [string]}
400crate::macros::easy_enum! {opacity [float]}
401crate::macros::easy_enum! {perspective none [unit]}
402crate::macros::easy_enum! {backface-visibility visible hidden}
403crate::macros::easy_enum! {overflow-x visible hidden scroll auto}
404crate::macros::easy_enum! {overflow-y visible hidden scroll auto}
405crate::macros::easy_enum! {float none left right inline-start inline-end}
406crate::macros::easy_enum! {clear none left right inline-start inline-end both}
407crate::macros::easy_enum! {overflow-anchor auto none}
408
409#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
410pub enum UserSelect {
411 Initial,
412 Inherit,
413 Unset,
414 Auto,
415 None,
416 Text,
417 All,
418}
419
420#[rustfmt::skip]
421impl std::fmt::Display for UserSelect {
422 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
423 match self {
424 Self::Initial => "user-select:initial;-webkit-user-select:initial;-moz-user-select:initial;".fmt(f),
425 Self::Inherit => "user-select:inherit;-webkit-user-select:inherit;-moz-user-select:inherit;".fmt(f),
426 Self::Unset => "user-select:unset;-webkit-user-select:unset;-moz-user-select:unset;".fmt(f),
427 Self::Auto => "user-select:auto;-webkit-user-select:auto;-moz-user-select:auto;".fmt(f),
428 Self::None => "user-select:none;-webkit-user-select:none;-moz-user-select:none;".fmt(f),
429 Self::Text => "user-select:text;-webkit-user-select:text;-moz-user-select:text;".fmt(f),
430 Self::All => "user-select:all;-webkit-user-select:all;-moz-user-select:all;".fmt(f),
431 }
432 }
433}
434
435#[macro_export]
436macro_rules! user_select {
437 (initial) => {$crate::Property::UserSelect($crate::UserSelect::Initial)};
438 (inherit) => {$crate::Property::UserSelect($crate::UserSelect::Inherit)};
439 (unset) => {$crate::Property::UserSelect($crate::UserSelect::Unset)};
440 (auto) => {$crate::Property::UserSelect($crate::UserSelect::Auto)};
441 (none) => {$crate::Property::UserSelect($crate::UserSelect::None)};
442 (text) => {$crate::Property::UserSelect($crate::UserSelect::Text)};
443 (all) => {$crate::Property::UserSelect($crate::UserSelect::All)};
444}