Skip to main content

whisker_css/keyword/
linear.rs

1//! Keyword enums for Lynx's `linear-*` layout extension.
2//!
3//! Lynx ships its own linear-layout container as an alternative to
4//! CSS flexbox. The keywords are Lynx-specific and have no MDN
5//! equivalent. References:
6//! - <https://lynxjs.org/api/css/properties/linear-direction>
7//! - <https://lynxjs.org/api/css/properties/linear-orientation>
8//! - <https://lynxjs.org/api/css/properties/linear-gravity>
9//! - <https://lynxjs.org/api/css/properties/linear-cross-gravity>
10//! - <https://lynxjs.org/api/css/properties/linear-layout-gravity>
11
12use core::fmt;
13
14use crate::to_css::ToCss;
15
16/// The `linear-orientation` keyword. Lynx-specific replacement for
17/// `flex-direction` when using `display: linear`.
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
19pub enum LinearOrientation {
20    /// `horizontal` — main axis runs horizontally.
21    Horizontal,
22    /// `vertical` — main axis runs vertically.
23    Vertical,
24    /// `horizontal-reverse` — horizontal, reversed.
25    HorizontalReverse,
26    /// `vertical-reverse` — vertical, reversed.
27    VerticalReverse,
28}
29
30impl ToCss for LinearOrientation {
31    fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
32        dest.write_str(match self {
33            LinearOrientation::Horizontal => "horizontal",
34            LinearOrientation::Vertical => "vertical",
35            LinearOrientation::HorizontalReverse => "horizontal-reverse",
36            LinearOrientation::VerticalReverse => "vertical-reverse",
37        })
38    }
39}
40
41/// The `linear-gravity` keyword. Lynx-specific alignment along the
42/// main axis. **`linear-gravity` is deprecated**; prefer
43/// `justify-content` on a `display: flex` container instead.
44#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
45pub enum LinearGravity {
46    /// `none` — no gravity. Default.
47    None,
48    /// `top` — gravitate to the top edge.
49    Top,
50    /// `bottom` — gravitate to the bottom edge.
51    Bottom,
52    /// `left` — gravitate to the left edge.
53    Left,
54    /// `right` — gravitate to the right edge.
55    Right,
56    /// `center-vertical` — center along the vertical axis.
57    CenterVertical,
58    /// `center-horizontal` — center along the horizontal axis.
59    CenterHorizontal,
60    /// `space-between` — equal space between items.
61    SpaceBetween,
62    /// `start` — pack to the start edge.
63    Start,
64    /// `end` — pack to the end edge.
65    End,
66    /// `center` — pack to the center.
67    Center,
68}
69
70impl ToCss for LinearGravity {
71    fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
72        dest.write_str(match self {
73            LinearGravity::None => "none",
74            LinearGravity::Top => "top",
75            LinearGravity::Bottom => "bottom",
76            LinearGravity::Left => "left",
77            LinearGravity::Right => "right",
78            LinearGravity::CenterVertical => "center-vertical",
79            LinearGravity::CenterHorizontal => "center-horizontal",
80            LinearGravity::SpaceBetween => "space-between",
81            LinearGravity::Start => "start",
82            LinearGravity::End => "end",
83            LinearGravity::Center => "center",
84        })
85    }
86}
87
88/// The `linear-cross-gravity` keyword. Lynx-specific alignment along
89/// the cross axis. Comparable to `align-items` in flexbox.
90#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
91pub enum LinearCrossGravity {
92    /// `none` — no cross-axis alignment. Default.
93    None,
94    /// `start` — align to the cross-axis start.
95    Start,
96    /// `end` — align to the cross-axis end.
97    End,
98    /// `center` — center along the cross axis.
99    Center,
100    /// `stretch` — stretch across the cross axis.
101    Stretch,
102}
103
104impl ToCss for LinearCrossGravity {
105    fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
106        dest.write_str(match self {
107            LinearCrossGravity::None => "none",
108            LinearCrossGravity::Start => "start",
109            LinearCrossGravity::End => "end",
110            LinearCrossGravity::Center => "center",
111            LinearCrossGravity::Stretch => "stretch",
112        })
113    }
114}
115
116/// The `linear-layout-gravity` keyword. Lynx-specific per-child
117/// override for cross-axis alignment.
118#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
119pub enum LinearLayoutGravity {
120    /// `none` — defer to parent's `linear-cross-gravity`. Default.
121    None,
122    /// `start` — align to the cross-axis start.
123    Start,
124    /// `end` — align to the cross-axis end.
125    End,
126    /// `center` — center along the cross axis.
127    Center,
128    /// `stretch` — stretch across the cross axis.
129    Stretch,
130}
131
132impl ToCss for LinearLayoutGravity {
133    fn to_css(&self, dest: &mut dyn fmt::Write) -> fmt::Result {
134        dest.write_str(match self {
135            LinearLayoutGravity::None => "none",
136            LinearLayoutGravity::Start => "start",
137            LinearLayoutGravity::End => "end",
138            LinearLayoutGravity::Center => "center",
139            LinearLayoutGravity::Stretch => "stretch",
140        })
141    }
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn linear_orientation_all() {
150        let cases = [
151            (LinearOrientation::Horizontal, "horizontal"),
152            (LinearOrientation::Vertical, "vertical"),
153            (LinearOrientation::HorizontalReverse, "horizontal-reverse"),
154            (LinearOrientation::VerticalReverse, "vertical-reverse"),
155        ];
156        for (k, expected) in cases {
157            assert_eq!(k.to_css_string(), expected);
158        }
159    }
160
161    #[test]
162    fn linear_gravity_all() {
163        let cases = [
164            (LinearGravity::None, "none"),
165            (LinearGravity::Top, "top"),
166            (LinearGravity::Bottom, "bottom"),
167            (LinearGravity::Left, "left"),
168            (LinearGravity::Right, "right"),
169            (LinearGravity::CenterVertical, "center-vertical"),
170            (LinearGravity::CenterHorizontal, "center-horizontal"),
171            (LinearGravity::SpaceBetween, "space-between"),
172            (LinearGravity::Start, "start"),
173            (LinearGravity::End, "end"),
174            (LinearGravity::Center, "center"),
175        ];
176        for (k, expected) in cases {
177            assert_eq!(k.to_css_string(), expected);
178        }
179    }
180
181    #[test]
182    fn linear_cross_gravity_all() {
183        let cases = [
184            (LinearCrossGravity::None, "none"),
185            (LinearCrossGravity::Start, "start"),
186            (LinearCrossGravity::End, "end"),
187            (LinearCrossGravity::Center, "center"),
188            (LinearCrossGravity::Stretch, "stretch"),
189        ];
190        for (k, expected) in cases {
191            assert_eq!(k.to_css_string(), expected);
192        }
193    }
194
195    #[test]
196    fn linear_layout_gravity_all() {
197        let cases = [
198            (LinearLayoutGravity::None, "none"),
199            (LinearLayoutGravity::Start, "start"),
200            (LinearLayoutGravity::End, "end"),
201            (LinearLayoutGravity::Center, "center"),
202            (LinearLayoutGravity::Stretch, "stretch"),
203        ];
204        for (k, expected) in cases {
205            assert_eq!(k.to_css_string(), expected);
206        }
207    }
208}