From 474c2e97e092f2f730ebd98a413e09c8396b9a54 Mon Sep 17 00:00:00 2001 From: SGavrl <277843151+SGavrl@users.noreply.github.com> Date: Thu, 30 Jul 2026 22:51:37 +0000 Subject: [PATCH] Preserve container query state --- crates/obscura-render/src/css.rs | 400 +++++++++++++++++++++++++++-- crates/obscura-render/src/dom.rs | 12 + crates/obscura-render/src/lib.rs | 20 ++ crates/obscura-render/src/style.rs | 141 ++++++++++ 4 files changed, 556 insertions(+), 17 deletions(-) diff --git a/crates/obscura-render/src/css.rs b/crates/obscura-render/src/css.rs index af0923f..aa87e53 100644 --- a/crates/obscura-render/src/css.rs +++ b/crates/obscura-render/src/css.rs @@ -13,12 +13,64 @@ use std::collections::HashMap; use crate::LayoutStyle; +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +struct ContainerConditionId(u32); + +impl ContainerConditionId { + const NONE: Self = Self(0); +} + +#[derive(Clone, Debug, PartialEq)] +struct ContainerConditionNode { + parent: ContainerConditionId, + /// Comma-separated queries in one prelude are alternatives; parent-linked + /// nodes represent nested `@container` rules that must all match. + alternatives: Vec, +} + +#[derive(Clone, Debug, PartialEq)] +struct ContainerQuery { + name: Option, + condition: Option, +} + +#[derive(Clone, Debug, PartialEq)] +enum ContainerQueryExpr { + Feature(ContainerSizeFeature), + Not(Box), + And(Vec), + Or(Vec), +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum ContainerQueryAxis { Width, InlineSize } + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum ContainerQueryComparison { Min, Max } + +#[derive(Clone, Copy, Debug, PartialEq)] +struct ContainerSizeFeature { + axis: ContainerQueryAxis, + comparison: ContainerQueryComparison, + length: ContainerQueryLength, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum ContainerQueryLength { Px(f32), Em(f32), Rem(f32) } + +struct ParsedRule { + selector: String, + declarations: String, + container_condition_id: ContainerConditionId, +} + struct Rule { sel: CompiledSelector, normal_decls: String, important_decls: String, /// Source order, for breaking specificity ties (later wins). order: usize, + container_condition_id: ContainerConditionId, } struct PseudoRule { @@ -26,11 +78,14 @@ struct PseudoRule { normal_decls: String, important_decls: String, order: usize, + container_condition_id: ContainerConditionId, } /// An indexed set of author rules ready for fast per-element matching. pub struct Stylesheet { rules: Vec, + /// Index zero is the unconditional sentinel. + container_conditions: Vec, /// Final declarations from `@keyframes name { ... 100%/to { ... } }`. /// Static screenshots are taken after the requested settle interval, so a /// finite forwards-filled animation contributes this declaration block. @@ -47,6 +102,13 @@ pub struct Stylesheet { } impl Stylesheet { + /// Until Stage B supplies completed container geometry, preserved + /// conditional rules remain inactive rather than using viewport geometry. + fn container_condition_is_active(&self, id: ContainerConditionId) -> bool { + debug_assert!((id.0 as usize) < self.container_conditions.len()); + id == ContainerConditionId::NONE + } + /// Parse and index a set of raw CSS sources (the text of each `