use std::{
rc::{
Weak,
Rc,
},
};
use js_sys::Array;
use wasm_bindgen::{
prelude::Closure,
JsValue,
JsCast,
};
use web_sys::{
Element,
ResizeObserver as ResizeObserver1,
ResizeObserverOptions,
};
use crate::{
scope_any,
ScopeValue,
};
pub struct ResizeObserver_ {
pub js_resize_observer: ResizeObserver1,
_js_cb: ScopeValue,
}
#[derive(Clone)]
pub struct ResizeObserver(pub Rc<ResizeObserver_>);
pub struct ObserveHandle {
target: Element,
resize_observer: Weak<ResizeObserver_>,
}
impl ResizeObserver {
pub fn new(cb: impl Fn(Array) + 'static) -> Self {
let js_cb = Closure::wrap(Box::new(move |entries: Array, _| -> () {
cb(entries);
}) as Box<dyn Fn(Array, JsValue)>);
let resize_observer = ResizeObserver1::new(js_cb.as_ref().unchecked_ref()).unwrap();
return Self(Rc::new(ResizeObserver_ {
js_resize_observer: resize_observer,
_js_cb: scope_any(js_cb),
}));
}
pub fn observe(&self, target: &Element) -> ObserveHandle {
self.0.js_resize_observer.observe(target.dyn_ref().unwrap());
return ObserveHandle {
target: target.clone(),
resize_observer: Rc::downgrade(&self.0),
}
}
pub fn observe_with_options(&self, target: &Element, opts: &ResizeObserverOptions) -> ObserveHandle {
self.0.js_resize_observer.observe_with_options(target.dyn_ref().unwrap(), opts);
return ObserveHandle {
target: target.clone(),
resize_observer: Rc::downgrade(&self.0),
}
}
}
impl Drop for ObserveHandle {
fn drop(&mut self) {
let Some(resize_observer) = self.resize_observer.upgrade() else {
return;
};
resize_observer.js_resize_observer.unobserve(self.target.dyn_ref().unwrap());
}
}