material_yew/
drawer.rs

1mod drawer_app_content;
2mod drawer_header;
3mod drawer_subtitle;
4mod drawer_title;
5
6pub use drawer_app_content::*;
7pub use drawer_header::*;
8pub use drawer_subtitle::*;
9pub use drawer_title::*;
10
11use crate::{bool_to_option, WeakComponentLink};
12use gloo::events::EventListener;
13use wasm_bindgen::prelude::*;
14use web_sys::Node;
15use yew::prelude::*;
16use yew::virtual_dom::AttrValue;
17
18#[wasm_bindgen(module = "/build/mwc-drawer.js")]
19extern "C" {
20    #[derive(Debug)]
21    #[wasm_bindgen(extends = Node)]
22    type Drawer;
23
24    #[wasm_bindgen(getter, static_method_of = Drawer)]
25    fn _dummy_loader() -> JsValue;
26
27    #[wasm_bindgen(method, getter)]
28    fn open(this: &Drawer) -> bool;
29
30    #[wasm_bindgen(method, setter)]
31    fn set_open(this: &Drawer, value: bool);
32
33    #[wasm_bindgen(method, setter)]
34    fn set_type(this: &Drawer, value: &JsValue);
35}
36
37loader_hack!(Drawer);
38
39/// The `mwc-drawer` component
40///
41/// [MWC Documentation](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/drawer)
42pub struct MatDrawer {
43    node_ref: NodeRef,
44    opened_listener: Option<EventListener>,
45    closed_listener: Option<EventListener>,
46}
47
48/// Props for [`MatDrawer`]
49///
50/// MWC Documentation:
51///
52/// - [Properties](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/drawer#propertiesattributes)
53/// - [Events](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/drawer#events)
54#[derive(Properties, PartialEq, Clone)]
55pub struct DrawerProps {
56    #[prop_or_default]
57    pub open: bool,
58    #[prop_or_default]
59    pub has_header: bool,
60    #[prop_or_default]
61    pub drawer_type: Option<AttrValue>,
62    /// Binds to `opened` event on `mwc-drawer`
63    ///
64    /// See events docs to learn more.
65    #[prop_or_default]
66    pub onopened: Callback<()>,
67    /// Binds to `closed` event on `mwc-drawer`
68    ///
69    /// See events docs to learn more.
70    #[prop_or_default]
71    pub onclosed: Callback<()>,
72    #[prop_or_default]
73    pub drawer_link: WeakComponentLink<MatDrawer>,
74    pub children: Children,
75}
76
77impl Component for MatDrawer {
78    type Message = ();
79    type Properties = DrawerProps;
80
81    fn create(ctx: &Context<Self>) -> Self {
82        ctx.props()
83            .drawer_link
84            .borrow_mut()
85            .replace(ctx.link().clone());
86        Drawer::ensure_loaded();
87        Self {
88            node_ref: NodeRef::default(),
89            opened_listener: None,
90            closed_listener: None,
91        }
92    }
93
94    fn view(&self, ctx: &Context<Self>) -> Html {
95        let props = ctx.props();
96        html! {
97        <mwc-drawer hasHeader={bool_to_option(props.has_header)} ref={self.node_ref.clone()}>
98            {props.children.clone()}
99        </mwc-drawer>
100               }
101    }
102
103    fn rendered(&mut self, ctx: &Context<Self>, _first_render: bool) {
104        let props = ctx.props();
105        let element = self.node_ref.cast::<Drawer>().unwrap();
106        element.set_type(&JsValue::from(
107            props
108                .drawer_type
109                .as_ref()
110                .map(|s| s.as_ref())
111                .unwrap_or_default(),
112        ));
113        element.set_open(props.open);
114
115        if self.opened_listener.is_none() {
116            let onopen_callback = props.onopened.clone();
117            self.opened_listener = Some(EventListener::new(
118                &element,
119                "MDCDrawer:opened",
120                move |_| {
121                    onopen_callback.emit(());
122                },
123            ));
124        }
125
126        if self.closed_listener.is_none() {
127            let onclose_callback = props.onclosed.clone();
128            self.closed_listener = Some(EventListener::new(
129                &element,
130                "MDCDrawer:closed",
131                move |_| {
132                    onclose_callback.emit(());
133                },
134            ));
135        }
136    }
137}
138
139impl WeakComponentLink<MatDrawer> {
140    /// A convenience method to for `drawer.open = !drawer.open`
141    pub fn flip_open_state(&self) {
142        let node_ref = self
143            .borrow()
144            .as_ref()
145            .unwrap()
146            .get_component()
147            .unwrap()
148            .node_ref
149            .clone();
150        let element = node_ref.cast::<Drawer>().unwrap();
151        let open = element.open();
152        element.set_open(!open);
153    }
154}