Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d6d4a1d
wip: initial leptos port for use-rect
omar-mohamed-khallaf Jun 16, 2025
2084f92
wip: complete implementation
omar-mohamed-khallaf Jun 16, 2025
7abb9a8
Merge branch 'RustForWeb:main' into main
omar-mohamed-khallaf Jun 16, 2025
4b3a8db
Don't call callbacks with the lock held
omar-mohamed-khallaf Jun 16, 2025
641e780
Optimize searching for observed element
omar-mohamed-khallaf Jun 16, 2025
d7e5fdf
Merge branch 'RustForWeb:main' into main
omar-mohamed-khallaf Jun 16, 2025
c2bedcd
replace Arc with Rc
omar-mohamed-khallaf Jun 16, 2025
39fe6a2
use borderbox for ResizeObserver option
omar-mohamed-khallaf Jun 16, 2025
539fb3d
rename variable
omar-mohamed-khallaf Jun 17, 2025
f4b4bd6
Hashmap implementation for use-rect
omar-mohamed-khallaf Jun 17, 2025
01ff2d1
refactor: new implementation using js_sys
omar-mohamed-khallaf Jun 17, 2025
3a56d34
fix: dependencies
omar-mohamed-khallaf Jun 17, 2025
336b59b
fix: use_rect
omar-mohamed-khallaf Jun 17, 2025
a6e22b1
fix: use_rect
omar-mohamed-khallaf Jun 17, 2025
c5b0260
Revert "fix: use_rect"
omar-mohamed-khallaf Jun 17, 2025
da54910
fix: call callbacks when the element is found
omar-mohamed-khallaf Jun 17, 2025
c57d8ee
feat: generalize observe_element and use it for use_size
omar-mohamed-khallaf Jun 17, 2025
2bc4835
use dyn_ref when possible
omar-mohamed-khallaf Jun 17, 2025
4fa5c81
fix typo
omar-mohamed-khallaf Jun 17, 2025
a354d34
fix: logical error
omar-mohamed-khallaf Jun 17, 2025
511d127
chores
omar-mohamed-khallaf Jun 17, 2025
769b865
fix: remove duplicate search for element in map
omar-mohamed-khallaf Jun 18, 2025
a566886
refactor
omar-mohamed-khallaf Jun 18, 2025
4440706
fix: remove duplicate set of size on initial observation
omar-mohamed-khallaf Jun 18, 2025
3892a47
Merge branch 'main' into main
omar-mohamed-khallaf Jun 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Don't call callbacks with the lock held
Signed-off-by: Omar Mohamed <[email protected]>
  • Loading branch information
omar-mohamed-khallaf committed Jun 16, 2025
commit 4b3a8db628ff90483004a44de3d987982ba58a30
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/primitives/core/rect/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ repository.workspace = true
version.workspace = true

[dependencies]
dashmap.workspace = true
web-sys = { workspace = true, features = [
"DomRect",
"Element",
Expand Down
42 changes: 29 additions & 13 deletions packages/primitives/core/rect/src/observe_element_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ use web_sys::{
wasm_bindgen::{JsCast, closure::Closure},
};

struct ObservedData {
// TODO: should it be Arc or Rc
type Callback<'a> = Arc<dyn Fn(DomRect) + 'a>;

#[derive(Clone)]
struct ObservedData<'a> {
rect: DomRect,
callbacks: Vec<Option<Box<dyn Fn(DomRect)>>>,
callbacks: Vec<Option<Callback<'a>>>,
}

struct ObservedElement {
element: Element,
observed_data: ObservedData,
observed_data: ObservedData<'static>,
}

static OBSERVED_ELEMENTS: LazyLock<Arc<RwLock<Vec<SendWrapper<ObservedElement>>>>> =
Expand All @@ -24,13 +28,8 @@ static RESIZE_OBSERVER: LazyLock<SendWrapper<ResizeObserver>> = LazyLock::new(||
Closure::new(|entries: Vec<ResizeObserverEntry>| {
for entry in entries {
let target = entry.target();
if let Some(observed_element) = OBSERVED_ELEMENTS
.read()
.expect("Read lock should be acquired.")
.iter()
.find(|observed_element| observed_element.element == target)
{
for callback in observed_element.observed_data.callbacks.iter().flatten() {
if let Some(observed_element) = find_observed_data(&target) {
for callback in observed_element.callbacks.iter().flatten() {
callback(entry.target().get_bounding_client_rect().clone());
}
}
Expand All @@ -43,6 +42,21 @@ static RESIZE_OBSERVER: LazyLock<SendWrapper<ResizeObserver>> = LazyLock::new(||
)
});

fn find_observed_data(element: &Element) -> Option<ObservedData<'static>> {
OBSERVED_ELEMENTS
.read()
.expect("Read lock should be acquired.")
.iter()
.find(|observed_element| observed_element.element == *element)
.map(|observed_element| observed_element.observed_data.clone())
}

/// uses `ResizeObserver` to observe an element an calls all the registered callbacks when element's
/// size changes
///
/// # Panics
///
/// Panics if failed to acquire locks
#[allow(clippy::significant_drop_tightening)]
pub fn observe_element_rect<C>(
element_to_observe: &Element,
Expand Down Expand Up @@ -74,7 +88,7 @@ where
observed_element
.observed_data
.callbacks
.push(Some(Box::new(callback)));
.push(Some(Arc::new(callback)));

callback_idx = observed_element.observed_data.callbacks.len() - 1;
}
Expand All @@ -86,9 +100,11 @@ where
element: element_to_observe.clone(),
observed_data: ObservedData {
rect: DomRect::new().expect("DomRect should be created"),
callbacks: vec![Some(Box::new(callback))],
callbacks: vec![Some(Arc::new(callback))],
},
}));

RESIZE_OBSERVER.observe(element_to_observe);
}

Box::new(move || {
Expand All @@ -112,8 +128,8 @@ where
.iter()
.any(std::option::Option::is_some)
{
lock.remove(idx);
RESIZE_OBSERVER.unobserve(element);
lock.remove(idx);
}
}
})
Expand Down