leptos_use/
use_media_query.rs1#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports, dead_code))]
2
3use crate::use_event_listener;
4use cfg_if::cfg_if;
5use leptos::ev::change;
6use leptos::prelude::*;
7use leptos::reactive::wrappers::read::Signal;
8use std::cell::RefCell;
9use std::rc::Rc;
10
11pub fn use_media_query(query: impl Into<Signal<String>>) -> Signal<bool> {
46 let query = query.into();
47
48 let (matches, set_matches) = signal(false);
49
50 cfg_if! { if #[cfg(not(feature = "ssr"))] {
51 let media_query: Rc<RefCell<Option<web_sys::MediaQueryList>>> = Rc::new(RefCell::new(None));
52 let remove_listener: RemoveListener = Rc::new(RefCell::new(None));
53
54 let listener = Rc::new(RefCell::new(Rc::new(|_| {}) as Rc<dyn Fn(web_sys::Event)>));
55
56 let cleanup = {
57 let remove_listener = Rc::clone(&remove_listener);
58
59 move || {
60 if let Some(remove_listener) = remove_listener.take().as_ref() {
61 remove_listener();
62 }
63 }
64 };
65
66 let update = {
67 let cleanup = cleanup.clone();
68 let listener = Rc::clone(&listener);
69
70 Rc::new(move || {
71 cleanup();
72
73 let mut media_query = media_query.borrow_mut();
74 *media_query = window().match_media(&query.get()).unwrap_or(None);
75
76 if let Some(media_query) = media_query.as_ref() {
77 set_matches.set(media_query.matches());
78
79 let listener = Rc::clone(&*listener.borrow());
80
81 remove_listener.replace(Some(Box::new(use_event_listener(
82 media_query.clone(),
83 change,
84 move |e| listener(e),
85 ))));
86 } else {
87 set_matches.set(false);
88 }
89 })
90 };
91
92 {
93 let update = Rc::clone(&update);
94 listener.replace(Rc::new(move |_| update()) as Rc<dyn Fn(web_sys::Event)>);
95 }
96
97 Effect::new(move |_| update());
98
99 on_cleanup({
100 let cleanup = send_wrapper::SendWrapper::new(cleanup);
101 #[allow(clippy::redundant_closure)]
102 move || cleanup()
103 });
104 }}
105
106 matches.into()
107}
108
109type RemoveListener = Rc<RefCell<Option<Box<dyn Fn()>>>>;