Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,6 @@ features = [
"ResizeObserverEntry",
"Selection",
"ShadowRoot",
"VisualViewport",
"Window",
]
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn convert_offset_parent_relative_rect_to_viewport_relative_rect(
}

let html_offset = if !is_offset_parent_an_element && !is_fixed {
get_html_offset(&document_element, &scroll, Some(true))
get_html_offset(&document_element, &scroll)
} else {
Coords::new(0.0)
};
Expand Down
15 changes: 2 additions & 13 deletions packages/dom/src/utils/get_html_offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,10 @@ use web_sys::Element;

use crate::utils::get_window_scroll_bar_x::get_window_scroll_bar_x;

pub fn get_html_offset(
document_element: &Element,
scroll: &NodeScroll,
ignore_scrollbar_x: Option<bool>,
) -> Coords {
let ignore_scrollbar_x = ignore_scrollbar_x.unwrap_or(false);

pub fn get_html_offset(document_element: &Element, scroll: &NodeScroll) -> Coords {
let html_rect = document_element.get_bounding_client_rect();
let x = html_rect.left() + scroll.scroll_left
- if ignore_scrollbar_x {
0.0
} else {
// RTL <body> scrollbar.
get_window_scroll_bar_x(document_element, Some(&html_rect))
};
- get_window_scroll_bar_x(document_element, Some(&html_rect));
let y = html_rect.top() + scroll.scroll_top;

Coords { x, y }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn get_rect_relative_to_offset_parent(
}

let html_offset = if !is_offset_parent_an_element && !is_fixed {
get_html_offset(&document_element, &scroll, None)
get_html_offset(&document_element, &scroll)
} else {
Coords::new(0.0)
};
Expand Down
73 changes: 63 additions & 10 deletions packages/dom/src/utils/get_viewport_rect.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,71 @@
use floating_ui_utils::{Rect, Strategy, dom::get_document_element};
use floating_ui_utils::{
Rect, Strategy,
dom::{get_computed_style, get_document_element, get_window, is_web_kit},
};
use web_sys::Element;

pub fn get_viewport_rect(element: &Element, _strategy: Strategy) -> Rect {
// let window = get_window(Some(element));
use crate::utils::get_window_scroll_bar_x::get_window_scroll_bar_x;

// Safety check: ensure the scrollbar space is reasonable in case this calculation is affected by unusual styles.
// Most scrollbars leave 15-18px of space.
const SCROLLBAR_MAX: f64 = 25.0;

pub fn get_viewport_rect(element: &Element, strategy: Strategy) -> Rect {
let window = get_window(Some(element));
let html = get_document_element(Some(element.into()));
// TODO
// let visual_viewport = window.visual_viewport;
let visual_viewport = window.visual_viewport();

let x = 0.0;
let y = 0.0;
let width = html.client_width() as f64;
let height = html.client_height() as f64;
let mut x = 0.0;
let mut y = 0.0;
let mut width = html.client_width() as f64;
let mut height = html.client_height() as f64;

// TODO: visual viewport
if let Some(visual_viewport) = visual_viewport {
width = visual_viewport.width();
height = visual_viewport.height();

let visual_viewport_based = is_web_kit();
if !visual_viewport_based || strategy == Strategy::Fixed {
x = visual_viewport.offset_left();
y = visual_viewport.offset_top();
}
}

let window_scrollbar_x = get_window_scroll_bar_x(&html, None);
// <html> `overflow: hidden` + `scrollbar-gutter: stable` reduces the visual width of the <html>,
// but this is not considered in the size of `html.client_width`.
if window_scrollbar_x <= 0.0 {
let doc = html
.owner_document()
.expect("Element should have owner document.");
let body = doc.body().expect("Document should have body.");
let body_styles = get_computed_style(&body);
let body_margin_inline = if doc.compat_mode() == "CSS1Compat" {
body_styles
.get_property_value("margin-left")
.expect("Computed style should have margin left.")
.parse::<f64>()
.unwrap_or(0.0)
+ body_styles
.get_property_value("margin-right")
.expect("Computed style should have margin right.")
.parse::<f64>()
.unwrap_or(0.0)
} else {
0.0
};
let clipping_stable_scrollbar_width =
((html.client_width() as f64) - (body.client_width() as f64) - body_margin_inline)
.abs();

if clipping_stable_scrollbar_width <= SCROLLBAR_MAX {
width -= clipping_stable_scrollbar_width;
}
} else if window_scrollbar_x <= SCROLLBAR_MAX {
// If the <body> scrollbar is on the left, the width needs to be extended
// by the scrollbar amount so there isn't extra space on the right.
width += window_scrollbar_x;
}

Rect {
x,
Expand Down
2 changes: 1 addition & 1 deletion upstream.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[releases]
core = "1.7.3"
dom = "1.7.3"
dom = "1.7.4"
utils = "0.2.10"
vue = "1.1.8"
Loading