material_dioxus/
lib.rs

1// See: https://github.com/rustwasm/wasm-bindgen/issues/2774
2// Can remove when wasm-bindgen is updated.
3#![allow(clippy::unused_unit)]
4#![doc = include_str!("../README.md")]
5
6use dioxus::prelude::ScopeState;
7use rand::distributions::Alphanumeric;
8use rand::distributions::DistString;
9use wasm_bindgen::prelude::*;
10use wasm_bindgen::JsValue;
11mod utils;
12
13// this macro is defined here so we can access it in the modules
14#[allow(unused)]
15macro_rules! loader_hack {
16    ($ty:ty) => {
17        #[allow(dead_code)]
18        static LOADED: std::sync::Once = std::sync::Once::new();
19        impl $ty {
20            #[allow(dead_code)]
21            fn ensure_loaded() {
22                LOADED.call_once(|| {
23                    <$ty>::_dummy_loader();
24                });
25            }
26        }
27    };
28}
29
30#[allow(unused)]
31macro_rules! component {
32    ($comp: ident, $props: ty, $html: expr, $mwc_to_initialize: ident, $mwc_name: literal) => {
33        paste::paste! {
34            #[doc = "The `mwc-" $mwc_name "` component"]
35            #[doc = ""]
36            #[doc = "[MWC Documentation](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/" $mwc_name ")"]
37            #[allow(non_snake_case)]
38            pub fn $comp(cx: Scope<$props>) -> Element {
39                $mwc_to_initialize::ensure_loaded();
40                $html(cx)
41            }
42        }
43   };
44    ('a, $comp: ident, $props: ty, $html: expr, $mwc_to_initialize: ident, $mwc_name: literal) => {
45        paste::paste! {
46            #[doc = "The `mwc-" $mwc_name "` component"]
47            #[doc = ""]
48            #[doc = "[MWC Documentation](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/" $mwc_name ")"]
49            #[allow(non_snake_case)]
50            pub fn $comp<'a>(cx: Scope<'a, $props<'a>>) -> Element<'a> {
51                $mwc_to_initialize::ensure_loaded();
52                $html(cx)
53            }
54        }
55   };
56}
57
58#[allow(unused)]
59macro_rules! string_attr {
60    ($value:expr) => {
61        ::dioxus::core::AttributeValue::Text(&$value)
62    };
63}
64
65#[allow(unused)]
66macro_rules! optional_string_attr {
67    ($value:expr) => {
68        $value
69            .as_ref()
70            .map(|s| {
71                if s.is_empty() {
72                    ::dioxus::core::AttributeValue::None
73                } else {
74                    ::dioxus::core::AttributeValue::Text(s.as_str())
75                }
76            })
77            .unwrap_or(::dioxus::core::AttributeValue::None)
78    };
79}
80
81#[allow(unused)]
82macro_rules! bool_attr {
83    ($value:expr) => {
84        $value
85            .then_some(::dioxus::core::AttributeValue::Bool(true))
86            .unwrap_or(::dioxus::core::AttributeValue::None)
87    };
88}
89
90#[allow(unused)]
91fn event_into_details(event: &web_sys::Event) -> JsValue {
92    JsValue::from(event)
93        .dyn_into::<web_sys::CustomEvent>()
94        .unwrap_or_else(|_| panic!("could not convert to CustomEvent"))
95        .detail()
96}
97
98#[allow(unused)]
99fn event_details_into<T: JsCast>(event: &web_sys::Event) -> T {
100    event_into_details(event).unchecked_into::<T>()
101}
102
103#[allow(unused)]
104fn use_id<'a>(cx: &'a ScopeState, prefix: &str) -> &'a str {
105    cx.use_hook(|| {
106        let mut id = format!("{prefix}-");
107        Alphanumeric.append_string(&mut rand::thread_rng(), &mut id, 11);
108        // rerender the component immediately, so that code depending on the ID works on "the
109        // first render".
110        cx.needs_update();
111        id
112    })
113    .as_str()
114}
115
116#[allow(unused)]
117fn get_elem_by_id(id: &str) -> Option<web_sys::Element> {
118    web_sys::window()
119        .unwrap()
120        .document()
121        .unwrap()
122        .get_element_by_id(id)
123}
124
125#[cfg(feature = "button")]
126pub mod button;
127#[cfg(feature = "button")]
128#[doc(hidden)]
129pub use button::MatButton;
130
131#[cfg(feature = "circular-progress")]
132pub mod circular_progress;
133#[cfg(feature = "circular-progress")]
134#[doc(hidden)]
135pub use circular_progress::MatCircularProgress;
136
137#[cfg(feature = "checkbox")]
138pub mod checkbox;
139#[cfg(feature = "checkbox")]
140#[doc(hidden)]
141pub use checkbox::MatCheckbox;
142
143#[cfg(feature = "circular-progress-four-color")]
144pub mod circular_progress_four_color;
145#[cfg(feature = "circular-progress-four-color")]
146#[doc(hidden)]
147pub use circular_progress_four_color::MatCircularProgressFourColor;
148
149#[cfg(feature = "drawer")]
150pub mod drawer;
151#[cfg(feature = "drawer")]
152#[doc(hidden)]
153pub use drawer::MatDrawer;
154
155#[cfg(feature = "top-app-bar")]
156pub mod top_app_bar;
157#[cfg(feature = "top-app-bar")]
158#[doc(hidden)]
159pub use top_app_bar::MatTopAppBar;
160
161#[cfg(feature = "icon-button")]
162pub mod icon_button;
163#[cfg(feature = "icon-button")]
164#[doc(hidden)]
165pub use icon_button::MatIconButton;
166
167#[cfg(feature = "fab")]
168pub mod fab;
169#[cfg(feature = "fab")]
170#[doc(hidden)]
171pub use fab::MatFab;
172
173#[cfg(feature = "formfield")]
174pub mod form_field;
175#[cfg(feature = "formfield")]
176#[doc(hidden)]
177pub use form_field::MatFormfield;
178
179#[cfg(feature = "icon")]
180pub mod icon;
181#[cfg(feature = "icon")]
182#[doc(hidden)]
183pub use icon::MatIcon;
184
185#[cfg(feature = "linear-progress")]
186pub mod linear_progress;
187#[cfg(feature = "linear-progress")]
188#[doc(hidden)]
189pub use linear_progress::MatLinearProgress;
190
191#[cfg(feature = "radio")]
192pub mod radio;
193#[cfg(feature = "radio")]
194#[doc(hidden)]
195pub use radio::MatRadio;
196
197#[cfg(feature = "switch")]
198pub mod switch;
199#[cfg(feature = "switch")]
200#[doc(hidden)]
201pub use switch::MatSwitch;
202
203#[cfg(feature = "top-app-bar-fixed")]
204pub mod top_app_bar_fixed;
205#[cfg(feature = "top-app-bar-fixed")]
206#[doc(hidden)]
207pub use top_app_bar_fixed::MatTopAppBarFixed;
208
209#[cfg(feature = "dialog")]
210pub mod dialog;
211#[cfg(feature = "dialog")]
212#[doc(hidden)]
213pub use dialog::MatDialog;
214
215#[cfg(feature = "list")]
216pub mod list;
217#[cfg(feature = "list")]
218#[doc(no_inline)]
219#[doc(hidden)]
220pub use list::{MatCheckListItem, MatList, MatListItem, MatListSeparator, MatRadioListItem};
221
222#[cfg(feature = "icon-button-toggle")]
223pub mod icon_button_toggle;
224#[cfg(feature = "icon-button-toggle")]
225#[doc(hidden)]
226pub use icon_button_toggle::MatIconButtonToggle;
227
228#[cfg(feature = "slider")]
229pub mod slider;
230#[cfg(feature = "slider")]
231#[doc(hidden)]
232pub use slider::MatSlider;
233
234#[cfg(feature = "tabs")]
235pub mod tabs;
236#[cfg(feature = "tabs")]
237#[doc(no_inline)]
238#[doc(hidden)]
239pub use tabs::{MatTab, MatTabBar};
240
241#[cfg(feature = "snackbar")]
242pub mod snackbar;
243#[cfg(feature = "snackbar")]
244#[doc(hidden)]
245pub use snackbar::MatSnackbar;
246
247#[cfg(any(feature = "textfield", feature = "textarea"))]
248pub mod text_inputs;
249#[cfg(feature = "textarea")]
250#[doc(no_inline)]
251#[doc(hidden)]
252pub use text_inputs::MatTextArea;
253#[cfg(feature = "textfield")]
254#[doc(no_inline)]
255#[doc(hidden)]
256pub use text_inputs::MatTextField;
257
258#[cfg(feature = "select")]
259pub mod select;
260#[cfg(feature = "select")]
261#[doc(hidden)]
262pub use select::MatSelect;
263
264#[cfg(feature = "menu")]
265pub mod menu;
266#[cfg(feature = "menu")]
267#[doc(hidden)]
268pub use menu::MatMenu;
269
270#[cfg(feature = "theming")]
271pub mod theming;
272#[cfg(feature = "theming")]
273#[doc(hidden)]
274pub use theming::MatTheme;
275
276#[cfg(feature = "palette")]
277pub mod palette;
278
279pub use utils::StaticCallback;
280
281#[wasm_bindgen(module = "/build/core.js")]
282extern "C" {
283    #[derive(Debug)]
284    type Ripple;
285
286    #[wasm_bindgen(getter, static_method_of = Ripple)]
287    fn _dummy_loader() -> JsValue;
288}
289
290loader_hack!(Ripple);