Skip to content

Commit

Permalink
Change ElementOrVirtual to own VirtualElement
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielleHuisman committed Mar 29, 2024
1 parent 3efe0f9 commit 74f343a
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 29 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion packages/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions packages/dom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
23 changes: 13 additions & 10 deletions packages/dom/src/auto_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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<ResizeObserver> = None;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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 || {
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/dom/src/platform/get_scale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
19 changes: 11 additions & 8 deletions packages/dom/src/utils/get_bounding_client_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ pub fn get_bounding_client_rect(
is_fixed_strategy: bool,
offset_parent: Option<DomElementOrWindow>,
) -> 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())
}
ElementOrVirtual::VirtualElement(virtual_element) => {
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 {
Expand All @@ -50,19 +50,22 @@ 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;
let mut width = client_rect.width / scale.x;
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()),
Expand Down
1 change: 1 addition & 0 deletions packages/utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ repository.workspace = true
version.workspace = true

[dependencies]
dyn-clone.workspace = true
serde.workspace = true
web-sys = { workspace = true, optional = true }

Expand Down
33 changes: 24 additions & 9 deletions packages/utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#[cfg(feature = "dom")]
pub mod dom;

use dyn_clone::DynClone;
use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -239,27 +240,39 @@ pub struct ElementRects {
pub floating: Rect,
}

#[derive(Clone)]
pub enum OwnedElementOrVirtual<Element> {
Element(Element),
VirtualElement(Box<dyn VirtualElement<Element>>),
}

#[derive(Copy, Clone)]
pub enum ElementOrVirtual<'a, Element> {
impl<Element> OwnedElementOrVirtual<Element> {
pub fn resolve(self) -> Option<Element> {
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<Element>),
VirtualElement(Box<dyn VirtualElement<Element>>),
}

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<Element> {
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)
}
Expand All @@ -268,12 +281,14 @@ impl<'a, Element> From<&'a Element> for ElementOrVirtual<'a, Element> {
/// Custom positioning reference element.
///
/// See <https://floating-ui.com/docs/virtual-elements> for the original documentation.
pub trait VirtualElement<Element> {
pub trait VirtualElement<Element>: DynClone {
fn get_bounding_client_rect(&self) -> ClientRectObject;

fn context_element(&self) -> Option<&Element>;
fn context_element(&self) -> Option<Element>;
}

dyn_clone::clone_trait_object!(<Element> VirtualElement<Element>);

#[derive(Clone, Debug)]
pub enum ElementOrWindow<'a, Element, Window> {
Element(&'a Element),
Expand Down

0 comments on commit 74f343a

Please sign in to comment.