Skip to main content

flams_web_utils/components/
layout.rs

1use std::borrow::Cow;
2
3use ftml_component_utils::inject_css;
4use leptos::prelude::*;
5
6#[component]
7pub fn Layout(
8    #[prop(optional)] layout_header: Option<LayoutHeader>,
9    #[prop(optional)] layout_sider: Option<LayoutSider>,
10    #[prop(optional)] layout_footer: Option<LayoutFooter>,
11    children: Children,
12    #[prop(optional)] class: Option<&'static str>,
13    #[prop(optional)] style: Option<&'static str>,
14) -> impl IntoView {
15    use ftml_component_utils::Scrollbar;
16    use leptos::either::Either::{Left, Right};
17    inject_css("flams-layout", include_str!("layout.css"));
18
19    if layout_header.is_none() && layout_footer.is_none() {
20        return if let Some(sider) = layout_sider {
21            let class: Cow<str> = class.map_or_else(
22                || "flams-layout-with-sider".into(),
23                |cls| format!("flams-layout-with-sider {cls}").into(),
24            );
25            view! {
26                <div class=class style=style>
27                    <div class="flams-layout-sider">
28                        {sider.into_view()}
29                    </div>
30                    <div>
31                        <Scrollbar>{children()}</Scrollbar>
32                    </div>
33                </div>
34            }
35            .into_any()
36        } else {
37            leptos::html::div()
38                .class(class)
39                .style(style)
40                .child(children())
41                .into_any()
42        };
43    }
44
45    let class: Cow<str> = class.map_or_else(
46        || "flams-layout".into(),
47        |cls| format!("flams-layout {cls}").into(),
48    );
49    let inner = move || {
50        if let Some(sider) = layout_sider {
51            Left(view! {
52                <div class="flams-layout-with-sider">
53                    <div class="flams-layout-sider">
54                        <Scrollbar>{sider.into_view()}</Scrollbar>
55                    </div>
56                    <div>
57                        <Scrollbar>{children()}</Scrollbar>
58                    </div>
59                </div>
60            })
61        } else {
62            Right(view!(<div><Scrollbar>{children()}</Scrollbar></div>))
63        }
64    };
65    view! {
66        <div class=class style=style>
67            {layout_header.map(LayoutHeader::into_view)}
68            {inner()}
69            {layout_footer.map(LayoutFooter::into_view)}
70        </div>
71    }
72    .into_any()
73}
74
75#[slot]
76pub struct LayoutHeader {
77    children: Children,
78    #[prop(optional)]
79    class: Option<&'static str>,
80    #[prop(optional)]
81    style: Option<&'static str>,
82}
83impl LayoutHeader {
84    fn into_view(self) -> impl IntoView {
85        let class: Cow<str> = self.class.map_or_else(
86            || "flams-layout-tf".into(),
87            |cls| format!("flams-layout-tf {cls}").into(),
88        );
89        leptos::html::div()
90            .class(class)
91            .style(self.style)
92            .child((self.children)())
93    }
94}
95
96#[slot]
97pub struct LayoutFooter {
98    children: Children,
99    #[prop(optional)]
100    class: Option<&'static str>,
101    #[prop(optional)]
102    style: Option<&'static str>,
103}
104impl LayoutFooter {
105    fn into_view(self) -> impl IntoView {
106        let class: Cow<str> = self.class.map_or_else(
107            || "flams-layout-tf".into(),
108            |cls| format!("flams-layout-tf {cls}").into(),
109        );
110        leptos::html::div()
111            .class(class)
112            .style(self.style)
113            .child((self.children)())
114    }
115}
116
117#[slot]
118pub struct LayoutSider {
119    children: Children,
120    #[prop(optional)]
121    class: Option<&'static str>,
122    #[prop(optional)]
123    style: Option<&'static str>,
124}
125impl LayoutSider {
126    fn into_view(self) -> impl IntoView {
127        leptos::html::div()
128            .class(self.class)
129            .style(self.style)
130            .child((self.children)())
131    }
132}