flams_web_utils/components/
layout.rs1use 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}