dioxus_resize_observer/
lib.rs1use dioxus::prelude::*;
2use dioxus_use_mounted::UseMounted;
3use dioxus_web::WebEventExt;
4use js_sys::Array;
5use std::rc::Rc;
6use wasm_bindgen::closure::Closure;
7use wasm_bindgen::JsCast;
8use web_sys::DomRectReadOnly;
9use web_sys::ResizeObserver;
10use web_sys::ResizeObserverEntry;
11
12pub type Rect = DomRectReadOnly;
13
14pub fn use_size(mounted: UseMounted) -> Rect {
33 let resize = use_resize(mounted);
34 let resize_ref = resize.read();
35 resize_ref
36 .clone()
37 .unwrap_or_else(|| DomRectReadOnly::new().unwrap())
38}
39
40pub fn use_resize(mounted: UseMounted) -> Signal<Option<Rect>> {
42 let mut state_ref: Signal<Option<State>> = use_signal(|| None);
43 let mut size_ref = use_signal(|| None);
44
45 use_effect(move || {
46 if let Some(mounted) = mounted.signal.read().clone() {
47 maybe_unobserve(state_ref);
49
50 let on_resize = Closure::<dyn FnMut(Array)>::new(move |entries: Array| {
52 let entry = entries.at(0);
53 let entry: ResizeObserverEntry = entry.dyn_into().unwrap();
54 size_ref.set(Some(entry.content_rect()));
55 });
56 let resize_observer = ResizeObserver::new(on_resize.as_ref().unchecked_ref()).unwrap();
57
58 let raw_elem = get_raw_element(&mounted);
60 resize_observer.observe(&raw_elem);
61
62 state_ref.set(Some(State {
64 resize_observer,
65 mounted,
66 _on_resize: on_resize,
67 }));
68 } else {
69 maybe_unobserve(state_ref);
71 }
72 });
73
74 size_ref
75}
76
77struct State {
79 resize_observer: ResizeObserver,
81
82 mounted: Rc<MountedData>,
84
85 _on_resize: Closure<dyn FnMut(Array)>,
87}
88
89fn get_raw_element(mounted: &MountedData) -> web_sys::Element {
91 mounted.try_as_web_event().unwrap()
92}
93
94fn maybe_unobserve(mut state_ref: Signal<Option<State>>) {
96 if let Some(state) = state_ref.write().take() {
97 let raw_elem = get_raw_element(&state.mounted);
98 state.resize_observer.unobserve(&raw_elem);
99 }
100}