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
24 changes: 12 additions & 12 deletions packages/core/src/compute_coords_from_placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ pub fn compute_coords_from_placement(
};

let rtl = rtl.unwrap_or(false);
match get_alignment(placement) {
Some(Alignment::Start) => {
coords.update_axis(alignment_axis, |value| {
value - common_align * (if rtl && is_vertical { -1.0 } else { 1.0 })
});
}
Some(Alignment::End) => {
coords.update_axis(alignment_axis, |value| {
value + common_align * (if rtl && is_vertical { -1.0 } else { 1.0 })
});
}
None => {}

if let Some(alignment) = get_alignment(placement) {
coords.update_axis(alignment_axis, |value| {
value
- common_align
* (if alignment == Alignment::End {
1.0
} else {
-1.0
})
* (if rtl && is_vertical { -1.0 } else { 1.0 })
});
}

coords
Expand Down
22 changes: 11 additions & 11 deletions packages/core/src/middleware/auto_placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,23 +236,12 @@ impl<Element: Clone + PartialEq, Window: Clone + PartialEq> Middleware<Element,
allowed_placements
};

let overflow = platform.detect_overflow(
MiddlewareState {
elements: elements.clone(),
..state
},
options.detect_overflow.unwrap_or_default(),
);

let current_index = data.index;
let current_placement = placements.get(current_index);

if let Some(current_placement) = current_placement {
let current_placement = *current_placement;

let alignment_sides =
get_alignment_sides(current_placement, rects, platform.is_rtl(elements.floating));

// Make `compute_coords` start from the right place.
if placement != current_placement {
return MiddlewareReturn {
Expand All @@ -266,6 +255,17 @@ impl<Element: Clone + PartialEq, Window: Clone + PartialEq> Middleware<Element,
};
}

let overflow = platform.detect_overflow(
MiddlewareState {
elements: elements.clone(),
..state
},
options.detect_overflow.unwrap_or_default(),
);

let alignment_sides =
get_alignment_sides(current_placement, rects, platform.is_rtl(elements.floating));

let current_overflows = vec![
overflow.side(get_side(current_placement)),
overflow.side(alignment_sides.0),
Expand Down
47 changes: 23 additions & 24 deletions packages/core/src/middleware/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,27 @@ impl<Element: Clone + PartialEq + 'static, Window: Clone + PartialEq + 'static>
.get_client_rects(elements.reference)
.unwrap_or(vec![]);

// No rects (e.g. a hidden or detached reference, or a collapsed range) -
// keep the existing reference rect rather than resetting to an invalid
// one with non-finite values.
if native_client_rects.is_empty() {
return MiddlewareReturn {
x: None,
y: None,
data: None,
reset: None,
};
}

let client_rects = get_rects_by_line(native_client_rects.clone());
let fallback = rect_to_client_rect(get_bounding_rect(native_client_rects));
let padding_object = get_padding_object(padding);

let get_bounding_client_rect = move || {
// There are two rects and they are disjoined.
if client_rects.len() == 2
&& client_rects[0].left > client_rects[1].right
&& (client_rects[0].left > client_rects[1].right
|| client_rects[1].left > client_rects[0].right)
&& let Some(x) = options.x
&& let Some(y) = options.y
{
Expand Down Expand Up @@ -222,19 +235,13 @@ impl<Element: Clone + PartialEq + 'static, Window: Clone + PartialEq + 'static>
} else {
last_rect.right
};
let width = right - left;
let height = bottom - top;

return ClientRectObject {
return rect_to_client_rect(Rect {
x: left,
y: top,
width,
height,
top,
right,
bottom,
left,
};
width: right - left,
height: bottom - top,
});
}

let is_left_side = placement.side() == Side::Left;
Expand All @@ -261,21 +268,13 @@ impl<Element: Clone + PartialEq + 'static, Window: Clone + PartialEq + 'static>

let top = measure_rects.first().expect("Enough elements exist.").top;
let bottom = measure_rects.last().expect("Enough elements exist.").bottom;
let left = min_left;
let right = max_right;
let width = right - left;
let height = bottom - top;

return ClientRectObject {
x: left,
return rect_to_client_rect(Rect {
x: min_left,
y: top,
width,
height,
top,
right,
bottom,
left,
};
width: max_right - min_left,
height: bottom - top,
});
}

fallback.clone()
Expand Down
44 changes: 20 additions & 24 deletions packages/core/src/middleware/shift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,34 +192,30 @@ impl<Element: Clone + PartialEq + 'static, Window: Clone + PartialEq + 'static>
let mut main_axis_coord = coords.axis(main_axis);
let mut cross_axis_coord = coords.axis(cross_axis);

if check_main_axis {
let min_side = match main_axis {
Axis::X => Side::Left,
Axis::Y => Side::Top,
};
let max_side = match main_axis {
Axis::X => Side::Right,
Axis::Y => Side::Bottom,
};
let min = main_axis_coord + overflow.side(min_side);
let max = main_axis_coord - overflow.side(max_side);
let clamp_coord = |axis: Axis, coord: f64| -> f64 {
clamp(
coord
+ overflow.side(if axis == Axis::Y {
Side::Top
} else {
Side::Left
}),
coord,
coord
- overflow.side(if axis == Axis::Y {
Side::Bottom
} else {
Side::Right
}),
)
};

main_axis_coord = clamp(min, main_axis_coord, max);
if check_main_axis {
main_axis_coord = clamp_coord(main_axis, main_axis_coord);
}

if check_cross_axis {
let min_side = match cross_axis {
Axis::X => Side::Left,
Axis::Y => Side::Top,
};
let max_side = match cross_axis {
Axis::X => Side::Right,
Axis::Y => Side::Bottom,
};
let min = cross_axis_coord + overflow.side(min_side);
let max = cross_axis_coord - overflow.side(max_side);

cross_axis_coord = clamp(min, cross_axis_coord, max);
cross_axis_coord = clamp_coord(cross_axis, cross_axis_coord);
}

let limited_coords = limiter.compute(MiddlewareState {
Expand Down
21 changes: 2 additions & 19 deletions packages/core/src/middleware/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,27 +207,10 @@ impl<Element: Clone + PartialEq, Window: Clone + PartialEq> Middleware<Element,
}

if no_shift && alignment.is_none() {
let x_min = overflow.left.max(0.0);
let x_max = overflow.right.max(0.0);
let y_min = overflow.top.max(0.0);
let y_max = overflow.bottom.max(0.0);

if is_y_axis {
available_width = width
- 2.0
* (if x_min != 0.0 || x_max != 0.0 {
x_min + x_max
} else {
overflow.left.max(overflow.right)
});
available_width = width - 2.0 * overflow.left.max(overflow.right);
} else {
available_height = height
- 2.0
* (if y_min != 0.0 || y_max != 0.0 {
y_min + y_max
} else {
overflow.top.max(overflow.bottom)
});
available_height = height - 2.0 * overflow.top.max(overflow.bottom);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ pub enum Boundary<Element> {
#[derive(Clone, Debug, PartialEq)]
pub enum RootBoundary {
Viewport,
LayoutViewport,
Document,
Rect(Rect),
}
Expand Down
75 changes: 28 additions & 47 deletions packages/dom/src/platform/get_clipping_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use floating_ui_utils::{
dom::{
OverflowAncestor, get_computed_style, get_document_element, get_node_name,
get_overflow_ancestors, get_parent_node, is_containing_block, is_last_traversable_node,
is_overflow_element, is_top_layer,
is_top_layer,
},
rect_to_client_rect,
};
Expand Down Expand Up @@ -49,7 +49,8 @@ fn get_client_rect_from_clipping_ancestor(
ElementOrRootBoundary::Element(element) => {
get_inner_bounding_client_rect(&element, strategy)
}
ElementOrRootBoundary::RootBoundary(RootBoundary::Viewport) => {
ElementOrRootBoundary::RootBoundary(RootBoundary::Viewport)
| ElementOrRootBoundary::RootBoundary(RootBoundary::LayoutViewport) => {
get_viewport_rect(&get_document_element(Some(element.into())), strategy)
}
ElementOrRootBoundary::RootBoundary(RootBoundary::Document) => {
Expand All @@ -69,23 +70,6 @@ fn get_client_rect_from_clipping_ancestor(
rect_to_client_rect(rect)
}

fn has_fixed_position_ancestor(element: &Element, stop_node: &Node) -> bool {
let parent_node = get_parent_node(element);
if &parent_node == stop_node
|| !parent_node.is_instance_of::<Element>()
|| is_last_traversable_node(&parent_node)
{
false
} else {
let element = parent_node.unchecked_into::<Element>();
get_computed_style(&element)
.get_property_value("position")
.expect("Computed style should have position.")
== "fixed"
|| has_fixed_position_ancestor(&element, stop_node)
}
}

fn get_clipping_element_ancestors(element: &Element) -> Vec<Element> {
// TODO: cache

Expand All @@ -99,7 +83,7 @@ fn get_clipping_element_ancestors(element: &Element) -> Vec<Element> {
OverflowAncestor::VisualViewport(_) => None,
})
.collect();
let mut current_containing_block_computed_style: Option<CssStyleDeclaration> = None;
let mut last_kept_computed_style: Option<CssStyleDeclaration> = None;
let element_is_fixed = get_computed_style(element)
.get_property_value("position")
.expect("Computed style should have position.")
Expand All @@ -116,37 +100,34 @@ fn get_clipping_element_ancestors(element: &Element) -> Vec<Element> {
let computed_style = get_computed_style(current_element);
let current_node_is_containing = is_containing_block(current_element.into());

let position = computed_style
.get_property_value("position")
.expect("Computed style should have position");

if !current_node_is_containing && position == "fixed" {
current_containing_block_computed_style = None;
}

let should_drop_current_node = if element_is_fixed {
!current_node_is_containing && current_containing_block_computed_style.is_none()
} else {
(!current_node_is_containing
&& position == "static"
&& current_containing_block_computed_style
.as_ref()
.is_some_and(|style| {
let positon = style
.get_property_value("position")
.expect("Computed style should have position");

positon == "absolute" || positon == "fixed"
}))
|| (is_overflow_element(current_element)
&& !current_node_is_containing
&& has_fixed_position_ancestor(element, current_element))
};
// Position of the containing block chain below the current node. A fixed
// element whose containing block hasn't been found yet is a fixed chain.
let last_position =
if let Some(last_kept_computed_style) = last_kept_computed_style.as_ref() {
last_kept_computed_style
.get_property_value("position")
.expect("Computed style should have position")
} else {
if element_is_fixed { "fixed" } else { "" }.to_owned()
};

// A non-containing ancestor does not clip the element when the chain
// below it escapes it: a fixed chain escapes all ancestors up to the
// next containing block, an absolute chain escapes static ancestors.
let should_drop_current_node = !current_node_is_containing
&& (last_position == "fixed"
|| (last_position == "absolute"
&& computed_style
.get_property_value("position")
.expect("Computed style should have position")
== "static"));

if should_drop_current_node {
// Drop non-containing blocks.
result.retain(|ancestor| ancestor != current_element);
} else {
current_containing_block_computed_style = Some(computed_style);
// The kept node carries the chain position for the next iteration.
last_kept_computed_style = Some(computed_style);
}

current_node = get_parent_node(&current_node);
Expand Down
15 changes: 7 additions & 8 deletions packages/dom/src/utils/get_css_dimensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ pub fn get_css_dimensions(element: &Element) -> CssDimensions {
.parse::<f64>()
.unwrap_or(0.0);

let offset_width;
let offset_height;
if is_html_element(element) {
let (offset_width, offset_height) = if is_html_element(element) {
let element = element.unchecked_ref::<HtmlElement>();
offset_width = element.offset_width() as f64;
offset_height = element.offset_height() as f64;
(
element.offset_width() as f64,
element.offset_height() as f64,
)
} else {
offset_width = width;
offset_height = height;
}
(width, height)
};
let should_fallback = width.round() != offset_width || height.round() != offset_height;

CssDimensions {
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.5"
core = "1.8.0"
dom = "1.7.6"
utils = "0.2.12"
vue = "2.0.0"
Loading