yew_bs/components/
offcanvas.rs1use yew::prelude::*;
2use web_sys::Element;
3use wasm_bindgen::JsValue;
4use crate::interop::BsOffcanvas;
5#[derive(Clone, Copy, PartialEq, Debug)]
6pub enum OffcanvasPlacement {
7 Start,
8 End,
9 Top,
10 Bottom,
11}
12impl OffcanvasPlacement {
13 pub fn as_str(&self) -> &'static str {
14 match self {
15 OffcanvasPlacement::Start => "start",
16 OffcanvasPlacement::End => "end",
17 OffcanvasPlacement::Top => "top",
18 OffcanvasPlacement::Bottom => "bottom",
19 }
20 }
21}
22#[derive(Properties, PartialEq)]
24pub struct OffcanvasProps {
25 #[prop_or_default]
27 pub children: Children,
28 #[prop_or_default]
30 pub show: bool,
31 #[prop_or(OffcanvasPlacement::End)]
33 pub placement: OffcanvasPlacement,
34 #[prop_or(true)]
36 pub backdrop: bool,
37 #[prop_or(true)]
39 pub backdrop_close: bool,
40 #[prop_or(true)]
42 pub keyboard: bool,
43 #[prop_or(false)]
45 pub scroll: bool,
46 #[prop_or_default]
48 pub on_show: Option<Callback<()>>,
49 #[prop_or_default]
51 pub on_hide: Option<Callback<()>>,
52 #[prop_or_default]
54 pub on_shown: Option<Callback<()>>,
55 #[prop_or_default]
57 pub on_hidden: Option<Callback<()>>,
58 #[prop_or_default]
60 pub class: Option<AttrValue>,
61 #[prop_or_default]
63 pub node_ref: NodeRef,
64}
65#[function_component(Offcanvas)]
67pub fn offcanvas(props: &OffcanvasProps) -> Html {
68 let mut classes_vec = vec!["offcanvas".to_string()];
69 classes_vec.push(format!("offcanvas-{}", props.placement.as_str()));
70 if let Some(class) = &props.class {
71 classes_vec.push(class.to_string());
72 }
73 let classes = classes!(classes_vec);
74 let node_ref = props.node_ref.clone();
75 {
76 let show = props.show;
77 let backdrop = props.backdrop;
78 let backdrop_close = props.backdrop_close;
79 let keyboard = props.keyboard;
80 let scroll = props.scroll;
81 let on_show = props.on_show.clone();
82 let on_hide = props.on_hide.clone();
83 let on_shown = props.on_shown.clone();
84 let on_hidden = props.on_hidden.clone();
85 let node_ref = node_ref.clone();
86 use_effect_with(
87 (show, backdrop, backdrop_close, keyboard, scroll),
88 move |(show, backdrop, backdrop_close, keyboard, scroll)| {
89 if let Some(element) = node_ref.cast::<Element>() {
90 let options = js_sys::Object::new();
91 if *backdrop {
92 if *backdrop_close {
93 js_sys::Reflect::set(
94 &options,
95 &"backdrop".into(),
96 &true.into(),
97 )
98 .unwrap();
99 } else {
100 js_sys::Reflect::set(
101 &options,
102 &"backdrop".into(),
103 &"static".into(),
104 )
105 .unwrap();
106 }
107 } else {
108 js_sys::Reflect::set(&options, &"backdrop".into(), &false.into())
109 .unwrap();
110 }
111 js_sys::Reflect::set(
112 &options,
113 &"keyboard".into(),
114 &(*keyboard).into(),
115 )
116 .unwrap();
117 js_sys::Reflect::set(&options, &"scroll".into(), &(*scroll).into())
118 .unwrap();
119 let bs_offcanvas = BsOffcanvas::new(
120 &element,
121 Some(&JsValue::from(options)),
122 );
123 if *show {
124 bs_offcanvas.show();
125 } else {
126 bs_offcanvas.hide();
127 }
128 }
129 || ()
130 },
131 );
132 }
133 html! {
134 < div class = { classes } tabindex = "-1" ref = { node_ref } > { for props
135 .children.iter() } </ div >
136 }
137}
138#[derive(Properties, PartialEq)]
140pub struct OffcanvasHeaderProps {
141 #[prop_or_default]
143 pub children: Children,
144 #[prop_or_default]
146 pub class: Option<AttrValue>,
147}
148#[function_component(OffcanvasHeader)]
150pub fn offcanvas_header(props: &OffcanvasHeaderProps) -> Html {
151 let mut classes_vec = vec!["offcanvas-header".to_string()];
152 if let Some(class) = &props.class {
153 classes_vec.push(class.to_string());
154 }
155 let classes = classes!(classes_vec);
156 html! {
157 < div class = { classes } > { for props.children.iter() } </ div >
158 }
159}
160#[derive(Properties, PartialEq)]
162pub struct OffcanvasTitleProps {
163 #[prop_or_default]
165 pub children: Children,
166 #[prop_or_default]
168 pub class: Option<AttrValue>,
169}
170#[function_component(OffcanvasTitle)]
172pub fn offcanvas_title(props: &OffcanvasTitleProps) -> Html {
173 let mut classes_vec = vec!["offcanvas-title".to_string()];
174 if let Some(class) = &props.class {
175 classes_vec.push(class.to_string());
176 }
177 let classes = classes!(classes_vec);
178 html! {
179 < h5 class = { classes } > { for props.children.iter() } </ h5 >
180 }
181}
182#[derive(Properties, PartialEq)]
184pub struct OffcanvasBodyProps {
185 #[prop_or_default]
187 pub children: Children,
188 #[prop_or_default]
190 pub class: Option<AttrValue>,
191}
192#[function_component(OffcanvasBody)]
194pub fn offcanvas_body(props: &OffcanvasBodyProps) -> Html {
195 let mut classes_vec = vec!["offcanvas-body".to_string()];
196 if let Some(class) = &props.class {
197 classes_vec.push(class.to_string());
198 }
199 let classes = classes!(classes_vec);
200 html! {
201 < div class = { classes } > { for props.children.iter() } </ div >
202 }
203}