mirror of
https://github.com/lexmount/moli.git
synced 2026-10-30 16:07:24 +00:00
fix(layout): retain normal grid stretching for native form controls
Map native controls to compressible replaced leaves without the image-only replaced flag. Cover checkbox, radio and range normal alignment at 50 by 50 pixels. Validation: cargo fmt --all; cargo clippy --workspace --all-targets --all-features -- -D warnings; cargo nextest run --no-fail-fast (20283 passed, 18 skipped). Release v3 and five browser regression rounds. Full WPT recorded separately.
This commit is contained in:
@@ -138,7 +138,9 @@ where
|
||||
root_style.force_display_none();
|
||||
}
|
||||
if root_semantics.is_replaced() {
|
||||
root_style.mark_replaced();
|
||||
root_style.mark_replaced(
|
||||
root_semantics.replaced == Some(crate::LayoutReplacedKind::FormControl),
|
||||
);
|
||||
} else if matches!(
|
||||
root_semantics.category,
|
||||
crate::LayoutElementCategory::FormControl(crate::LayoutFormControlKind::Button)
|
||||
@@ -306,7 +308,9 @@ where
|
||||
}
|
||||
let metrics = self.source.replaced_metrics(source_node);
|
||||
if semantics.is_replaced() {
|
||||
style.mark_replaced();
|
||||
style.mark_replaced(
|
||||
semantics.replaced == Some(crate::LayoutReplacedKind::FormControl),
|
||||
);
|
||||
} else if matches!(
|
||||
semantics.category,
|
||||
crate::LayoutElementCategory::FormControl(crate::LayoutFormControlKind::Button)
|
||||
|
||||
@@ -2121,8 +2121,11 @@ impl ResolvedLayoutStyle {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn mark_replaced(&mut self) {
|
||||
self.taffy.item_is_replaced = true;
|
||||
pub(crate) fn mark_replaced(&mut self, is_form_control: bool) {
|
||||
// Taffy distinguishes native controls from images for normal grid/OOF
|
||||
// stretch. Both remain compressible replaced leaves in block layout.
|
||||
self.taffy.item_is_replaced = !is_form_control;
|
||||
self.taffy.item_is_compressible_replaced = is_form_control;
|
||||
}
|
||||
|
||||
pub(crate) fn resolved_aspect_ratio(
|
||||
|
||||
@@ -709,6 +709,53 @@ fn grid_item_placement_and_self_alignment_use_the_selected_grid_area() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_form_controls_stretch_under_normal_grid_alignment() {
|
||||
use moli_layout::{LayoutFormControlKind, LayoutInputControlKind};
|
||||
for kind in [
|
||||
LayoutInputControlKind::Checkbox,
|
||||
LayoutInputControlKind::Radio,
|
||||
LayoutInputControlKind::Range,
|
||||
] {
|
||||
let mut control = FixtureNode::html("control", "input", Vec::new());
|
||||
control.semantics = LayoutElementSemantics::new(
|
||||
LayoutNamespace::Html,
|
||||
"input",
|
||||
LayoutElementCategory::FormControl(LayoutFormControlKind::Input(kind)),
|
||||
Some(LayoutReplacedKind::FormControl),
|
||||
);
|
||||
let source = FixtureSource {
|
||||
nodes: vec![FixtureNode::div("grid", vec![1]), control],
|
||||
};
|
||||
let mut styles = FixtureStyles::default();
|
||||
styles.0.insert(
|
||||
0,
|
||||
resolved(
|
||||
LayoutDisplay::Grid,
|
||||
Style {
|
||||
display: Display::Grid,
|
||||
size: Size {
|
||||
width: length(50.0),
|
||||
height: length(50.0),
|
||||
},
|
||||
grid_template_columns: vec![length(50.0)],
|
||||
grid_template_rows: vec![length(50.0)],
|
||||
..Style::default()
|
||||
},
|
||||
PaintColor::TRANSPARENT,
|
||||
),
|
||||
);
|
||||
styles
|
||||
.0
|
||||
.insert(1, resolved(LayoutDisplay::Block, Style::default(), RED));
|
||||
let snapshot = render(&source, &mut styles, PaintViewport::new(100, 100, 1.0));
|
||||
assert_rect(
|
||||
solid_rect(&snapshot, RED),
|
||||
PaintRect::new(0.0, 0.0, 50.0, 50.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn absolute_grid_items_use_retained_track_areas_in_both_directions() {
|
||||
for (direction, x) in [
|
||||
|
||||
Reference in New Issue
Block a user