From 74f343a83fddc9d1125a0ba89b716ee7cbf45393 Mon Sep 17 00:00:00 2001 From: Danielle Huisman Date: Fri, 29 Mar 2024 11:13:07 +0100 Subject: [PATCH] Change ElementOrVirtual to own VirtualElement --- Cargo.toml | 1 + packages/core/Cargo.toml | 2 +- packages/dom/Cargo.toml | 1 + packages/dom/src/auto_update.rs | 23 +++++++------ packages/dom/src/platform/get_scale.rs | 2 +- .../dom/src/utils/get_bounding_client_rect.rs | 19 ++++++----- packages/utils/Cargo.toml | 1 + packages/utils/src/lib.rs | 33 ++++++++++++++----- 8 files changed, 53 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b7702f..c7e2cc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/NixySoftware/floating-ui" version = "0.0.2" [workspace.dependencies] +dyn-clone = "1.0.17" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.114" wasm-bindgen = "0.2.92" diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 1df03f9..d5fbf49 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -9,7 +9,7 @@ repository.workspace = true version.workspace = true [dependencies] -dyn-clone = "1.0.17" +dyn-clone.workspace = true floating-ui-utils = { path = "../utils", version = "0.0.2" } serde.workspace = true serde_json.workspace = true diff --git a/packages/dom/Cargo.toml b/packages/dom/Cargo.toml index 8a4aa1c..45e5ccb 100644 --- a/packages/dom/Cargo.toml +++ b/packages/dom/Cargo.toml @@ -9,6 +9,7 @@ repository.workspace = true version.workspace = true [dependencies] +dyn-clone.workspace = true # TODO: remove log = "0.4.21" floating-ui-core = { path = "../core", version = "0.0.2" } diff --git a/packages/dom/src/auto_update.rs b/packages/dom/src/auto_update.rs index a172da9..32ccddb 100644 --- a/packages/dom/src/auto_update.rs +++ b/packages/dom/src/auto_update.rs @@ -108,13 +108,13 @@ pub fn auto_update( let layout_shift = options.layout_shift.unwrap_or(true); let animation_frame = options.animation_frame.unwrap_or(false); - let reference_element = reference.resolve(); + let reference_element = reference.clone().resolve(); let ancestors = match ancestor_scoll || ancestor_resize { true => { let mut ancestors = vec![]; - if let Some(reference) = reference_element { + if let Some(reference) = reference_element.as_ref() { ancestors = get_overflow_ancestors(reference, ancestors, true); } @@ -152,10 +152,13 @@ pub fn auto_update( } } - let cleanup_observe_move = reference_element.and_then(|reference_element| match layout_shift { - true => Some(observe_move(reference_element, update.clone())), - false => None, - }); + let cleanup_observe_move = + reference_element + .as_ref() + .and_then(|reference_element| match layout_shift { + true => Some(observe_move(reference_element, update.clone())), + false => None, + }); let reobserve_frame = -1; let mut resize_observer: Option = None; @@ -183,7 +186,7 @@ pub fn auto_update( ResizeObserver::new(resize_closure.into_js_value().unchecked_ref()) .expect("Resize observer should be created."); - if let Some(reference) = reference_element { + if let Some(reference) = reference_element.as_ref() { if !animation_frame { local_resize_observer.observe(reference); } @@ -210,8 +213,8 @@ pub fn auto_update( let owned = match reference { ElementOrVirtual::Element(e) => OwnedElementOrVirtual::Element(e.clone()), - ElementOrVirtual::VirtualElement(ve) => panic!("virtual element"), - // ElementOrVirtual::VirtualElement(ve) => OwnedElementOrVirtual::VirtualElement(ve.clone()), + // ElementOrVirtual::VirtualElement(ve) => panic!("virtual element"), + ElementOrVirtual::VirtualElement(ve) => OwnedElementOrVirtual::VirtualElement(ve.clone()), }; *frame_loop_closure_clone.borrow_mut() = Some(Closure::new(move || { @@ -221,7 +224,7 @@ pub fn auto_update( match &owned { OwnedElementOrVirtual::Element(e) => ElementOrVirtual::Element(e), OwnedElementOrVirtual::VirtualElement(ve) => { - ElementOrVirtual::VirtualElement(&**ve) + ElementOrVirtual::VirtualElement(ve.clone()) } }, false, diff --git a/packages/dom/src/platform/get_scale.rs b/packages/dom/src/platform/get_scale.rs index f9e1d8b..dc643f0 100644 --- a/packages/dom/src/platform/get_scale.rs +++ b/packages/dom/src/platform/get_scale.rs @@ -13,7 +13,7 @@ pub fn get_scale(element_or_virtual: ElementOrVirtual) -> Coords { let CssDimensions { dimensions, should_fallback, - } = get_css_dimensions(dom_element); + } = get_css_dimensions(&dom_element); let x = match should_fallback { true => rect.width().round(), false => rect.width(), diff --git a/packages/dom/src/utils/get_bounding_client_rect.rs b/packages/dom/src/utils/get_bounding_client_rect.rs index 02dcd1d..5baa8da 100644 --- a/packages/dom/src/utils/get_bounding_client_rect.rs +++ b/packages/dom/src/utils/get_bounding_client_rect.rs @@ -29,7 +29,7 @@ pub fn get_bounding_client_rect( is_fixed_strategy: bool, offset_parent: Option, ) -> ClientRectObject { - let client_rect = match element_or_virtual { + let client_rect = match &element_or_virtual { ElementOrVirtual::Element(element) => { dom_rect_to_client_rect_object(element.get_bounding_client_rect()) } @@ -37,7 +37,7 @@ pub fn get_bounding_client_rect( virtual_element.get_bounding_client_rect() } }; - let dom_element = element_or_virtual.resolve(); + let dom_element = element_or_virtual.clone().resolve(); let scale = match include_scale { true => match &offset_parent { @@ -50,11 +50,14 @@ pub fn get_bounding_client_rect( false => Coords::new(1.0), }; - let visual_offsets = - match should_add_visual_offsets(dom_element, is_fixed_strategy, offset_parent.clone()) { - true => get_visual_offsets(dom_element), - false => Coords::new(0.0), - }; + let visual_offsets = match should_add_visual_offsets( + dom_element.as_ref(), + is_fixed_strategy, + offset_parent.clone(), + ) { + true => get_visual_offsets(dom_element.as_ref()), + false => Coords::new(0.0), + }; let mut x = (client_rect.left + visual_offsets.x) / scale.x; let mut y = (client_rect.top + visual_offsets.y) / scale.y; @@ -62,7 +65,7 @@ pub fn get_bounding_client_rect( let mut height = client_rect.height / scale.y; if let Some(dom_element) = dom_element { - let window = get_window(Some(dom_element)); + let window = get_window(Some(&dom_element)); let offset_window = match offset_parent { Some(DomElementOrWindow::Element(element)) => Some(get_window(Some(element))), Some(DomElementOrWindow::Window(window)) => Some(window.clone()), diff --git a/packages/utils/Cargo.toml b/packages/utils/Cargo.toml index 9f2b730..5a969af 100644 --- a/packages/utils/Cargo.toml +++ b/packages/utils/Cargo.toml @@ -9,6 +9,7 @@ repository.workspace = true version.workspace = true [dependencies] +dyn-clone.workspace = true serde.workspace = true web-sys = { workspace = true, optional = true } diff --git a/packages/utils/src/lib.rs b/packages/utils/src/lib.rs index eed834a..09fae02 100644 --- a/packages/utils/src/lib.rs +++ b/packages/utils/src/lib.rs @@ -7,6 +7,7 @@ #[cfg(feature = "dom")] pub mod dom; +use dyn_clone::DynClone; use serde::{Deserialize, Serialize}; #[derive(Copy, Clone, Debug, PartialEq)] @@ -239,27 +240,39 @@ pub struct ElementRects { pub floating: Rect, } +#[derive(Clone)] pub enum OwnedElementOrVirtual { Element(Element), VirtualElement(Box>), } -#[derive(Copy, Clone)] -pub enum ElementOrVirtual<'a, Element> { +impl OwnedElementOrVirtual { + pub fn resolve(self) -> Option { + match self { + OwnedElementOrVirtual::Element(element) => Some(element), + OwnedElementOrVirtual::VirtualElement(virtal_element) => { + virtal_element.context_element() + } + } + } +} + +#[derive(Clone)] +pub enum ElementOrVirtual<'a, Element: Clone> { Element(&'a Element), - VirtualElement(&'a dyn VirtualElement), + VirtualElement(Box>), } -impl<'a, Element> ElementOrVirtual<'a, Element> { - pub fn resolve(&self) -> Option<&'a Element> { +impl<'a, Element: Clone> ElementOrVirtual<'a, Element> { + pub fn resolve(self) -> Option { match self { - ElementOrVirtual::Element(element) => Some(element), + ElementOrVirtual::Element(element) => Some(element.clone()), ElementOrVirtual::VirtualElement(virtal_element) => virtal_element.context_element(), } } } -impl<'a, Element> From<&'a Element> for ElementOrVirtual<'a, Element> { +impl<'a, Element: Clone> From<&'a Element> for ElementOrVirtual<'a, Element> { fn from(value: &'a Element) -> Self { ElementOrVirtual::Element(value) } @@ -268,12 +281,14 @@ impl<'a, Element> From<&'a Element> for ElementOrVirtual<'a, Element> { /// Custom positioning reference element. /// /// See for the original documentation. -pub trait VirtualElement { +pub trait VirtualElement: DynClone { fn get_bounding_client_rect(&self) -> ClientRectObject; - fn context_element(&self) -> Option<&Element>; + fn context_element(&self) -> Option; } +dyn_clone::clone_trait_object!( VirtualElement); + #[derive(Clone, Debug)] pub enum ElementOrWindow<'a, Element, Window> { Element(&'a Element),