2023-07-14 22:43:19 +01:00
|
|
|
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports, dead_code))]
|
|
|
|
|
2023-06-10 03:19:00 +01:00
|
|
|
use crate::use_event_listener;
|
2023-07-14 22:43:19 +01:00
|
|
|
use cfg_if::cfg_if;
|
2023-06-10 03:19:00 +01:00
|
|
|
use leptos::ev::change;
|
|
|
|
use leptos::*;
|
2023-06-24 01:12:43 +01:00
|
|
|
use std::cell::RefCell;
|
2023-06-10 03:19:00 +01:00
|
|
|
use std::rc::Rc;
|
|
|
|
|
|
|
|
/// Reactive [Media Query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Testing_media_queries).
|
|
|
|
///
|
|
|
|
/// ## Demo
|
|
|
|
///
|
|
|
|
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_media_query)
|
|
|
|
///
|
|
|
|
/// ## Usage
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # use leptos::*;
|
|
|
|
/// # use leptos_use::use_media_query;
|
|
|
|
/// #
|
|
|
|
/// # #[component]
|
2023-07-27 18:06:36 +01:00
|
|
|
/// # fn Demo() -> impl IntoView {
|
2023-06-10 03:19:00 +01:00
|
|
|
/// #
|
2023-07-27 18:06:36 +01:00
|
|
|
/// let is_large_screen = use_media_query("(min-width: 1024px)");
|
2023-06-10 03:19:00 +01:00
|
|
|
///
|
2023-07-27 18:06:36 +01:00
|
|
|
/// let is_dark_preferred = use_media_query("(prefers-color-scheme: dark)");
|
2023-06-10 03:19:00 +01:00
|
|
|
/// #
|
2023-07-27 18:06:36 +01:00
|
|
|
/// # view! { }
|
2023-06-10 03:19:00 +01:00
|
|
|
/// # }
|
|
|
|
/// ```
|
|
|
|
///
|
2023-07-14 22:43:19 +01:00
|
|
|
/// ## Server-Side Rendering
|
|
|
|
///
|
|
|
|
/// On the server this functions returns a Signal that is always `false`.
|
|
|
|
///
|
2023-06-10 03:47:31 +01:00
|
|
|
/// ## See also
|
|
|
|
///
|
|
|
|
/// * [`use_preferred_dark`]
|
|
|
|
/// * [`use_preferred_contrast`]
|
2023-07-27 18:06:36 +01:00
|
|
|
pub fn use_media_query(query: impl Into<MaybeSignal<String>>) -> Signal<bool> {
|
2023-06-10 03:19:00 +01:00
|
|
|
let query = query.into();
|
|
|
|
|
2023-07-27 18:06:36 +01:00
|
|
|
let (matches, set_matches) = create_signal(false);
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-07-14 22:43:19 +01:00
|
|
|
cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
|
|
|
let media_query: Rc<RefCell<Option<web_sys::MediaQueryList>>> = Rc::new(RefCell::new(None));
|
|
|
|
let remove_listener: RemoveListener = Rc::new(RefCell::new(None));
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-08-04 15:58:03 +01:00
|
|
|
let listener = Rc::new(RefCell::new(Rc::new(|_| {}) as Rc<dyn Fn(web_sys::Event)>));
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-07-14 22:43:19 +01:00
|
|
|
let cleanup = {
|
|
|
|
let remove_listener = Rc::clone(&remove_listener);
|
2023-06-13 17:48:32 +01:00
|
|
|
|
2023-07-14 22:43:19 +01:00
|
|
|
move || {
|
|
|
|
if let Some(remove_listener) = remove_listener.take().as_ref() {
|
|
|
|
remove_listener();
|
|
|
|
}
|
2023-06-13 17:48:32 +01:00
|
|
|
}
|
2023-07-14 22:43:19 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
let update = {
|
|
|
|
let cleanup = cleanup.clone();
|
|
|
|
let listener = Rc::clone(&listener);
|
|
|
|
|
2023-08-04 15:58:03 +01:00
|
|
|
Rc::new(move || {
|
2023-07-14 22:43:19 +01:00
|
|
|
cleanup();
|
|
|
|
|
|
|
|
let mut media_query = media_query.borrow_mut();
|
|
|
|
*media_query = window().match_media(&query.get()).unwrap_or(None);
|
|
|
|
|
|
|
|
if let Some(media_query) = media_query.as_ref() {
|
|
|
|
set_matches.set(media_query.matches());
|
|
|
|
|
2023-08-04 15:58:03 +01:00
|
|
|
let listener = Rc::clone(&*listener.borrow());
|
|
|
|
|
2023-07-14 22:43:19 +01:00
|
|
|
remove_listener.replace(Some(Box::new(use_event_listener(
|
2023-08-04 15:58:03 +01:00
|
|
|
media_query.clone(),
|
2023-07-14 22:43:19 +01:00
|
|
|
change,
|
2023-08-04 15:58:03 +01:00
|
|
|
move |e| listener(e),
|
2023-07-14 22:43:19 +01:00
|
|
|
))));
|
|
|
|
} else {
|
|
|
|
set_matches.set(false);
|
|
|
|
}
|
2023-08-04 15:58:03 +01:00
|
|
|
})
|
2023-07-14 22:43:19 +01:00
|
|
|
};
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-07-14 22:43:19 +01:00
|
|
|
{
|
2023-08-04 15:58:03 +01:00
|
|
|
let update = Rc::clone(&update);
|
|
|
|
listener.replace(Rc::new(move |_| update()) as Rc<dyn Fn(web_sys::Event)>);
|
2023-07-14 22:43:19 +01:00
|
|
|
}
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-07-27 18:06:36 +01:00
|
|
|
create_effect(move |_| update());
|
2023-06-10 03:19:00 +01:00
|
|
|
|
2023-07-27 18:06:36 +01:00
|
|
|
on_cleanup(cleanup);
|
2023-07-14 22:43:19 +01:00
|
|
|
}}
|
2023-06-10 03:19:00 +01:00
|
|
|
|
|
|
|
matches.into()
|
|
|
|
}
|
2023-06-10 19:43:51 +01:00
|
|
|
|
|
|
|
type RemoveListener = Rc<RefCell<Option<Box<dyn Fn()>>>>;
|