layoutcss_parser/components/
sidebar.rs

1use indoc::formatdoc;
2use crate::harmonic::get_harmonic;
3
4use std::collections::HashSet;
5const SIDEBAR_STYLE: &str = r#"
6  sidebar-l{
7    display: flex;
8    flex-wrap: wrap;
9  }
10"#;
11
12const SIDEBAR_REVERSE_STYLE: &str = r#"
13  sidebar-l[layout~=reverse]{
14    flex-wrap: wrap-reverse;
15  }
16"#;
17
18fn sidebar_shrink_style(reverse: bool) -> String {
19    formatdoc!(
20        r#"
21        sidebar-l[layout~=shrink]{{
22            align-items: flex-{};
23        }}
24        "#,
25        if reverse { "end" } else { "start" }
26    )
27}
28
29fn sidebar_gap_style(value: &str, harmonic: String) -> String {
30    formatdoc!(
31        r#"
32        sidebar-l[layout~="gap:{value}"]{{
33            gap: {harmonic};
34        }}
35        "#,
36    )
37}
38
39fn sidebar_gap_x_style(value: &str, harmonic: String) -> String {
40    formatdoc!(
41        r#"
42        sidebar-l[layout~="gap-x:{value}"]{{
43            column-gap: {harmonic};
44        }}
45        "#,
46    )
47}
48
49fn sidebar_gap_y_style(value: &str, harmonic: String) -> String {
50    formatdoc!(
51        r#"
52        sidebar-l[layout~="gap-y:{value}"]{{
53            row-gap: {harmonic};
54        }}
55        "#,
56    )
57}
58
59fn sidebar_group_style(
60    // they are String instead of &str
61    // because they have already been replaced
62    side_selector: String,
63    side_width_selector: String,
64    content_min_selector: String,
65    selector_one: &str,
66    selector_two: &str,
67    side_width: &str,
68    content_min: &str,
69) -> String {
70    formatdoc!(
71        r#"
72        sidebar-l{side_selector}{side_width_selector}{content_min_selector} > {selector_one}:not(outsider-l[layout~="disinherit"]) {{
73              flex-basis: {side_width};
74              flex-grow: 1;
75              min-inline-size: initial;
76              min-width:0;
77              min-height:0;
78        }}
79
80        sidebar-l{side_selector}{side_width_selector}{content_min_selector} > {selector_two}:not(outsider-l[layout~="disinherit"]) {{
81                flex-basis: 0;
82                flex-grow: 999;
83                min-inline-size: {content_min};
84        }}
85        "#,
86    )
87}
88
89pub fn sidebar_css(
90    reverse: bool,
91    shrink: bool,
92    side: Option<&str>,
93    side_width: Option<&str>,
94    content_min: Option<&str>,
95    gap: Option<&str>,
96    gap_x: Option<&str>,
97    gap_y: Option<&str>,
98    harmonic_ratio: f64,
99    set: &mut HashSet<String>,
100) {
101    set.insert(SIDEBAR_STYLE.to_string());
102    if reverse {
103        set.insert(SIDEBAR_REVERSE_STYLE.to_string());
104    }
105    if shrink {
106        set.insert(sidebar_shrink_style(reverse));
107    }
108    if let Some(value) = gap {
109        let harmonic_value = get_harmonic(&value, harmonic_ratio);
110        set.insert(sidebar_gap_style(value, harmonic_value));
111    }
112    if let Some(ref value) = gap_x {
113        let harmonic_value = get_harmonic(&value, harmonic_ratio);
114        set.insert(sidebar_gap_x_style(value, harmonic_value));
115    }
116    if let Some(ref value) = gap_y {
117        let harmonic_value = get_harmonic(&value, harmonic_ratio);
118        set.insert(sidebar_gap_y_style(value, harmonic_value));
119    }
120    if side.is_some() || side_width.is_some() || content_min.is_some() {
121        let side_width_selector = if let Some(ref val) = side_width {
122            formatdoc!(r#"[layout*="side-width:{}"]"#, val)
123        } else {
124            "".to_string()
125        };
126        let content_min_selector = if let Some(ref val) = content_min {
127            formatdoc!(r#"[layout*="content-min:{}"]"#, val)
128        } else {
129            "".to_string()
130        };
131        let side_selector = if let Some(ref val) = side {
132            formatdoc!(r#"[layout*="side:{}"]"#, val)
133        } else {
134            "".to_string()
135        };
136
137        let selector_one = match side {
138            None => ":first-child",
139            Some(val) if val == "left" => ":first-child",
140            _ => ":last-child",
141        };
142        let selector_two = if selector_one == ":first-child" {
143            ":last-child"
144        } else {
145            ":first-child"
146        };
147        let content_min = if let Some(val) = content_min {
148            val
149        } else {
150            "50%"
151        };
152        let side_width = if let Some(val) = side_width {
153            val
154        } else {
155            "auto"
156        };
157
158        set.insert(sidebar_group_style(
159            side_selector,
160            side_width_selector,
161            content_min_selector,
162            selector_one,
163            selector_two,
164            side_width,
165            content_min,
166        ));
167    }
168}