material_yew/
lib.rs

1#![doc(html_root_url = "/docs")]
2// See: https://github.com/rustwasm/wasm-bindgen/issues/2774
3// Can remove when wasm-bindgen is updated.
4#![allow(clippy::unused_unit)]
5//! A Material components library for [Yew](https://yew.rs). It wrpas around [Material Web Components](https://github.com/material-components/material-web) exposing Yew components.
6//!
7//! Example usage:
8//! ```rust
9//! use material_yew::MatButton;
10//! use yew::html;
11//!
12//! html! {
13//!     <MatButton label="Click me!" />
14//! };
15//! ```
16//!
17//! All the main components from the modules are re-exported.
18//! The specialized components used for populating slots and models can be
19//! accessed from their respective modules.
20//!
21//! More information can be found on the [website](https://yew-material.web.app) and in the [GitHub README](https://github.com/hamza1311/yew-material)
22
23use wasm_bindgen::prelude::*;
24use wasm_bindgen::{JsCast, JsValue};
25use web_sys::{CustomEvent, Event};
26mod utils;
27
28// this macro is defined here so we can access it in the modules
29macro_rules! loader_hack {
30    ($ty:ty) => {
31        #[allow(dead_code)]
32        static LOADED: std::sync::Once = std::sync::Once::new();
33        impl $ty {
34            #[allow(dead_code)]
35            fn ensure_loaded() {
36                LOADED.call_once(|| {
37                    <$ty>::_dummy_loader();
38                });
39            }
40        }
41    };
42}
43
44macro_rules! component {
45    ($comp: ident, $props: ty, $html: expr, $mwc_to_initialize: ident, $mwc_name: literal) => {
46        paste::paste! {
47            #[doc = "The `mwc-" $mwc_name "` component"]
48            #[doc = ""]
49            #[doc = "[MWC Documentation](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/"$mwc_name")"]
50            pub struct $comp;
51       }
52        impl yew::Component for $comp {
53            type Message = ();
54            type Properties = $props;
55
56            fn create(_: &Context<Self>) -> Self {
57                $mwc_to_initialize::ensure_loaded();
58                Self
59           }
60
61            fn view(&self, ctx: &Context<Self>) -> Html {
62                let props = ctx.props();
63                $html(props)
64           }
65       }
66   };
67}
68
69fn bool_to_option(value: bool) -> Option<AttrValue> {
70    value.then_some(AttrValue::Static("true"))
71}
72
73fn to_option_string(s: impl Display) -> Option<AttrValue> {
74    let s = s.to_string();
75    if s.is_empty() {
76        None
77    } else {
78        Some(AttrValue::from(s))
79    }
80}
81
82fn event_into_details(event: &Event) -> JsValue {
83    JsValue::from(event)
84        .dyn_into::<CustomEvent>()
85        .unwrap_or_else(|_| panic!("could not convert to CustomEvent"))
86        .detail()
87}
88fn event_details_into<T: JsCast>(event: &Event) -> T {
89    event_into_details(event).unchecked_into::<T>()
90}
91
92#[cfg(feature = "button")]
93pub mod button;
94#[cfg(feature = "button")]
95#[doc(hidden)]
96pub use button::MatButton;
97
98#[cfg(feature = "circular-progress")]
99pub mod circular_progress;
100#[cfg(feature = "circular-progress")]
101#[doc(hidden)]
102pub use circular_progress::MatCircularProgress;
103
104#[cfg(feature = "checkbox")]
105pub mod checkbox;
106#[cfg(feature = "checkbox")]
107#[doc(hidden)]
108pub use checkbox::MatCheckbox;
109
110#[cfg(feature = "circular-progress-four-color")]
111pub mod circular_progress_four_color;
112#[cfg(feature = "circular-progress-four-color")]
113#[doc(hidden)]
114pub use circular_progress_four_color::MatCircularProgressFourColor;
115
116#[cfg(feature = "drawer")]
117pub mod drawer;
118#[cfg(feature = "drawer")]
119#[doc(hidden)]
120pub use drawer::MatDrawer;
121
122#[cfg(feature = "top-app-bar")]
123pub mod top_app_bar;
124#[cfg(feature = "top-app-bar")]
125#[doc(hidden)]
126pub use top_app_bar::MatTopAppBar;
127
128#[cfg(feature = "icon-button")]
129pub mod icon_button;
130#[cfg(feature = "icon-button")]
131#[doc(hidden)]
132pub use icon_button::MatIconButton;
133
134#[cfg(feature = "fab")]
135pub mod fab;
136#[cfg(feature = "fab")]
137#[doc(hidden)]
138pub use fab::MatFab;
139
140#[cfg(feature = "formfield")]
141pub mod form_field;
142#[cfg(feature = "formfield")]
143#[doc(hidden)]
144pub use form_field::MatFormfield;
145
146#[cfg(feature = "icon")]
147pub mod icon;
148#[cfg(feature = "icon")]
149#[doc(hidden)]
150pub use icon::MatIcon;
151
152#[cfg(feature = "linear-progress")]
153pub mod linear_progress;
154#[cfg(feature = "linear-progress")]
155#[doc(hidden)]
156pub use linear_progress::MatLinearProgress;
157
158#[cfg(feature = "radio")]
159pub mod radio;
160#[cfg(feature = "radio")]
161#[doc(hidden)]
162pub use radio::MatRadio;
163
164#[cfg(feature = "switch")]
165pub mod switch;
166#[cfg(feature = "switch")]
167#[doc(hidden)]
168pub use switch::MatSwitch;
169
170#[cfg(feature = "top-app-bar-fixed")]
171pub mod top_app_bar_fixed;
172#[cfg(feature = "top-app-bar-fixed")]
173#[doc(hidden)]
174pub use top_app_bar_fixed::MatTopAppBarFixed;
175
176#[cfg(feature = "dialog")]
177pub mod dialog;
178#[cfg(feature = "dialog")]
179#[doc(hidden)]
180pub use dialog::MatDialog;
181
182#[cfg(feature = "list")]
183pub mod list;
184#[cfg(feature = "list")]
185#[doc(no_inline)]
186#[doc(hidden)]
187pub use list::{MatCheckListItem, MatList, MatListItem, MatRadioListItem};
188
189#[cfg(feature = "icon-button-toggle")]
190pub mod icon_button_toggle;
191#[cfg(feature = "icon-button-toggle")]
192#[doc(hidden)]
193pub use icon_button_toggle::MatIconButtonToggle;
194
195#[cfg(feature = "slider")]
196pub mod slider;
197#[cfg(feature = "slider")]
198#[doc(hidden)]
199pub use slider::MatSlider;
200
201#[cfg(feature = "tabs")]
202pub mod tabs;
203#[cfg(feature = "tabs")]
204#[doc(no_inline)]
205#[doc(hidden)]
206pub use tabs::{MatTab, MatTabBar};
207
208#[cfg(feature = "snackbar")]
209pub mod snackbar;
210#[cfg(feature = "snackbar")]
211#[doc(hidden)]
212pub use snackbar::MatSnackbar;
213
214#[cfg(any(feature = "textfield", feature = "textarea"))]
215pub mod text_inputs;
216#[cfg(feature = "textarea")]
217#[doc(no_inline)]
218#[doc(hidden)]
219pub use text_inputs::MatTextArea;
220#[cfg(feature = "textfield")]
221#[doc(no_inline)]
222#[doc(hidden)]
223pub use text_inputs::MatTextField;
224
225#[cfg(feature = "select")]
226pub mod select;
227#[cfg(feature = "select")]
228#[doc(hidden)]
229pub use select::MatSelect;
230
231#[cfg(feature = "menu")]
232pub mod menu;
233#[cfg(feature = "menu")]
234#[doc(hidden)]
235pub use menu::MatMenu;
236
237use std::fmt::Display;
238#[doc(hidden)]
239pub use utils::WeakComponentLink;
240use yew::virtual_dom::AttrValue;
241
242#[wasm_bindgen(module = "/build/core.js")]
243extern "C" {
244    #[derive(Debug)]
245    type Ripple;
246
247    #[wasm_bindgen(getter, static_method_of = Ripple)]
248    fn _dummy_loader() -> JsValue;
249}
250
251loader_hack!(Ripple);