diff --git a/CHANGELOG.md b/CHANGELOG.md index 98741b4bc..f27de4060 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- The tagged-pointer size types can now be inspected via a plain enum. `LengthPercentage`, `LengthPercentageAuto`, `Dimension`, `MinTrackSizingFunction` and `MaxTrackSizingFunction` each gain an `expand()` method returning a matching `Expanded*` enum (`ExpandedLengthPercentage`, `ExpandedDimension`, etc.) whose variants map one-to-one onto the type's constructors, along with `From` conversions in both directions. This makes it possible to read back the original value of a style property (for style inspection, serialization or integration with other libraries) without having to work with the raw `CompactLength` representation + - Support for `flex-wrap: balance` and the `flex-line-count` property from [CSS Flexbox Level 2](https://drafts.csswg.org/css-flexbox-2/#balance-values), gated behind a new on-by-default `flexbox_balance` cargo feature (which depends on `flexbox`): - `FlexWrap` gains `Balance` and `BalanceReverse` variants, and its CSS parser accepts the multi-keyword grammar `nowrap | [ wrap | wrap-reverse ] || balance`. When balancing, items are collected into flex lines such that the largest line is as small as possible (minimising the sum of squares of each line's free space), rather than greedily filling each line - `Style::flex_line_count` (and a corresponding `FlexboxContainerStyle::flex_line_count` trait method) specifies the minimum number of lines to balance items into (default `1`). When it is greater than 1 on any multi-line container (`wrap`, `wrap-reverse`, `balance` or `balance-reverse`), definite cross-axis available space for measuring items is divided between the requested number of lines (after subtracting cross-axis gaps), per the [CSSWG resolution](https://github.com/w3c/csswg-drafts/issues/13414) diff --git a/src/style/dimension.rs b/src/style/dimension.rs index d3ce5b87e..241e49ad2 100644 --- a/src/style/dimension.rs +++ b/src/style/dimension.rs @@ -76,6 +76,54 @@ impl LengthPercentage { pub const fn into_raw(self) -> CompactLength { self.0 } + + /// Expand the compact representation into an [`ExpandedLengthPercentage`] enum. + /// + /// This is useful when integrating with other libraries (e.g. for style inspection or + /// serialization) as it allows the value to be pattern-matched without having to work + /// with the raw [`CompactLength`] tagged-pointer representation directly. + pub fn expand(self) -> ExpandedLengthPercentage { + match self.0.tag() { + CompactLength::LENGTH_TAG => ExpandedLengthPercentage::Length(self.0.value()), + CompactLength::PERCENT_TAG => ExpandedLengthPercentage::Percent(self.0.value()), + #[cfg(feature = "calc")] + _ if self.0.is_calc() => ExpandedLengthPercentage::Calc(self.0.calc_value()), + _ => unreachable!("LengthPercentage contains a value with an invalid tag"), + } + } +} + +/// The expanded, non-compact representation of a [`LengthPercentage`]. +/// +/// Obtained via [`LengthPercentage::expand`]. Can be converted back into a [`LengthPercentage`] +/// using the [`From`] implementation. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ExpandedLengthPercentage { + /// An absolute length (see [`LengthPercentage::length`]) + Length(f32), + /// A percentage length (see [`LengthPercentage::percent`]) + Percent(f32), + /// A `calc()` value (see [`LengthPercentage::calc`]). The pointer is an opaque handle to the + /// calc representation, exactly as passed to the constructor. + #[cfg(feature = "calc")] + Calc(*const ()), +} + +impl From for ExpandedLengthPercentage { + fn from(value: LengthPercentage) -> Self { + value.expand() + } +} + +impl From for LengthPercentage { + fn from(value: ExpandedLengthPercentage) -> Self { + match value { + ExpandedLengthPercentage::Length(val) => Self::length(val), + ExpandedLengthPercentage::Percent(val) => Self::percent(val), + #[cfg(feature = "calc")] + ExpandedLengthPercentage::Calc(ptr) => Self::calc(ptr), + } + } } #[cfg(feature = "serde")] @@ -203,6 +251,58 @@ impl LengthPercentageAuto { pub fn is_auto(self) -> bool { self.0.is_auto() } + + /// Expand the compact representation into an [`ExpandedLengthPercentageAuto`] enum. + /// + /// This is useful when integrating with other libraries (e.g. for style inspection or + /// serialization) as it allows the value to be pattern-matched without having to work + /// with the raw [`CompactLength`] tagged-pointer representation directly. + pub fn expand(self) -> ExpandedLengthPercentageAuto { + match self.0.tag() { + CompactLength::LENGTH_TAG => ExpandedLengthPercentageAuto::Length(self.0.value()), + CompactLength::PERCENT_TAG => ExpandedLengthPercentageAuto::Percent(self.0.value()), + CompactLength::AUTO_TAG => ExpandedLengthPercentageAuto::Auto, + #[cfg(feature = "calc")] + _ if self.0.is_calc() => ExpandedLengthPercentageAuto::Calc(self.0.calc_value()), + _ => unreachable!("LengthPercentageAuto contains a value with an invalid tag"), + } + } +} + +/// The expanded, non-compact representation of a [`LengthPercentageAuto`]. +/// +/// Obtained via [`LengthPercentageAuto::expand`]. Can be converted back into a +/// [`LengthPercentageAuto`] using the [`From`] implementation. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ExpandedLengthPercentageAuto { + /// An absolute length (see [`LengthPercentageAuto::length`]) + Length(f32), + /// A percentage length (see [`LengthPercentageAuto::percent`]) + Percent(f32), + /// The automatic keyword (see [`LengthPercentageAuto::auto`]) + Auto, + /// A `calc()` value (see [`LengthPercentageAuto::calc`]). The pointer is an opaque handle to + /// the calc representation, exactly as passed to the constructor. + #[cfg(feature = "calc")] + Calc(*const ()), +} + +impl From for ExpandedLengthPercentageAuto { + fn from(value: LengthPercentageAuto) -> Self { + value.expand() + } +} + +impl From for LengthPercentageAuto { + fn from(value: ExpandedLengthPercentageAuto) -> Self { + match value { + ExpandedLengthPercentageAuto::Length(val) => Self::length(val), + ExpandedLengthPercentageAuto::Percent(val) => Self::percent(val), + ExpandedLengthPercentageAuto::Auto => Self::auto(), + #[cfg(feature = "calc")] + ExpandedLengthPercentageAuto::Calc(ptr) => Self::calc(ptr), + } + } } #[cfg(feature = "serde")] @@ -427,6 +527,86 @@ impl Dimension { pub fn value(self) -> f32 { self.0.value() } + + /// Expand the compact representation into an [`ExpandedDimension`] enum. + /// + /// This is useful when integrating with other libraries (e.g. for style inspection or + /// serialization) as it allows the value to be pattern-matched without having to work + /// with the raw [`CompactLength`] tagged-pointer representation directly. + pub fn expand(self) -> ExpandedDimension { + match self.0.tag() { + CompactLength::LENGTH_TAG => ExpandedDimension::Length(self.0.value()), + CompactLength::PERCENT_TAG => ExpandedDimension::Percent(self.0.value()), + CompactLength::AUTO_TAG => ExpandedDimension::Auto, + CompactLength::MIN_CONTENT_TAG => ExpandedDimension::MinContent, + CompactLength::MAX_CONTENT_TAG => ExpandedDimension::MaxContent, + CompactLength::FIT_CONTENT_PX_TAG => ExpandedDimension::FitContentPx(self.0.value()), + CompactLength::FIT_CONTENT_PERCENT_TAG => ExpandedDimension::FitContentPercent(self.0.value()), + CompactLength::FIT_CONTENT_KEYWORD_TAG => ExpandedDimension::FitContent, + CompactLength::STRETCH_TAG => ExpandedDimension::Stretch, + CompactLength::CONTENT_TAG => ExpandedDimension::Content, + #[cfg(feature = "calc")] + _ if self.0.is_calc() => ExpandedDimension::Calc(self.0.calc_value()), + _ => unreachable!("Dimension contains a value with an invalid tag"), + } + } +} + +/// The expanded, non-compact representation of a [`Dimension`]. +/// +/// Obtained via [`Dimension::expand`]. Can be converted back into a [`Dimension`] using the +/// [`From`] implementation. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ExpandedDimension { + /// An absolute length (see [`Dimension::length`]) + Length(f32), + /// A percentage length (see [`Dimension::percent`]) + Percent(f32), + /// The automatic keyword (see [`Dimension::auto`]) + Auto, + /// The `min-content` keyword (see [`Dimension::min_content`]) + MinContent, + /// The `max-content` keyword (see [`Dimension::max_content`]) + MaxContent, + /// A `fit-content(...)` value with a length limit (see [`Dimension::fit_content_px`]) + FitContentPx(f32), + /// A `fit-content(...)` value with a percentage limit (see [`Dimension::fit_content_percent`]) + FitContentPercent(f32), + /// The `fit-content` keyword with no limit (see [`Dimension::fit_content`]) + FitContent, + /// The `stretch` keyword (see [`Dimension::stretch`]) + Stretch, + /// The `content` keyword (see [`Dimension::content`]) + Content, + /// A `calc()` value (see [`Dimension::calc`]). The pointer is an opaque handle to the calc + /// representation, exactly as passed to the constructor. + #[cfg(feature = "calc")] + Calc(*const ()), +} + +impl From for ExpandedDimension { + fn from(value: Dimension) -> Self { + value.expand() + } +} + +impl From for Dimension { + fn from(value: ExpandedDimension) -> Self { + match value { + ExpandedDimension::Length(val) => Self::length(val), + ExpandedDimension::Percent(val) => Self::percent(val), + ExpandedDimension::Auto => Self::auto(), + ExpandedDimension::MinContent => Self::min_content(), + ExpandedDimension::MaxContent => Self::max_content(), + ExpandedDimension::FitContentPx(val) => Self::fit_content_px(val), + ExpandedDimension::FitContentPercent(val) => Self::fit_content_percent(val), + ExpandedDimension::FitContent => Self::fit_content(), + ExpandedDimension::Stretch => Self::stretch(), + ExpandedDimension::Content => Self::content(), + #[cfg(feature = "calc")] + ExpandedDimension::Calc(ptr) => Self::calc(ptr), + } + } } #[cfg(feature = "serde")] @@ -480,3 +660,71 @@ impl Rect { } } } + +#[cfg(test)] +mod expand_tests { + use super::*; + + /// A helper that produces a valid `calc()` handle for tests: a non-null pointer whose low + /// three bits are zero (as required by `CompactLength::calc`). + #[cfg(feature = "calc")] + fn calc_handle() -> *const () { + #[allow(dead_code)] + #[repr(align(8))] + struct Aligned(u64); + static HANDLE: Aligned = Aligned(0); + &HANDLE as *const Aligned as *const () + } + + #[test] + fn length_percentage_round_trips() { + let cases = [LengthPercentage::length(12.0), LengthPercentage::percent(0.5), LengthPercentage::ZERO]; + for value in cases { + assert_eq!(LengthPercentage::from(value.expand()), value); + assert_eq!(ExpandedLengthPercentage::from(value), value.expand()); + } + assert_eq!(LengthPercentage::length(3.0).expand(), ExpandedLengthPercentage::Length(3.0)); + assert_eq!(LengthPercentage::percent(0.25).expand(), ExpandedLengthPercentage::Percent(0.25)); + } + + #[test] + fn length_percentage_auto_round_trips() { + let cases = + [LengthPercentageAuto::length(12.0), LengthPercentageAuto::percent(0.5), LengthPercentageAuto::auto()]; + for value in cases { + assert_eq!(LengthPercentageAuto::from(value.expand()), value); + } + assert_eq!(LengthPercentageAuto::auto().expand(), ExpandedLengthPercentageAuto::Auto); + } + + #[test] + fn dimension_round_trips_all_keywords() { + let cases = [ + Dimension::length(12.0), + Dimension::percent(0.5), + Dimension::auto(), + Dimension::min_content(), + Dimension::max_content(), + Dimension::fit_content_px(30.0), + Dimension::fit_content_percent(0.75), + Dimension::fit_content(), + Dimension::stretch(), + Dimension::content(), + ]; + for value in cases { + assert_eq!(Dimension::from(value.expand()), value); + } + assert_eq!(Dimension::fit_content_px(30.0).expand(), ExpandedDimension::FitContentPx(30.0)); + assert_eq!(Dimension::content().expand(), ExpandedDimension::Content); + } + + #[cfg(feature = "calc")] + #[test] + fn calc_round_trips() { + let handle = calc_handle(); + assert_eq!(LengthPercentage::calc(handle).expand(), ExpandedLengthPercentage::Calc(handle)); + assert_eq!(LengthPercentage::from(ExpandedLengthPercentage::Calc(handle)), LengthPercentage::calc(handle)); + assert_eq!(Dimension::calc(handle).expand(), ExpandedDimension::Calc(handle)); + assert_eq!(LengthPercentageAuto::calc(handle).expand(), ExpandedLengthPercentageAuto::Calc(handle)); + } +} diff --git a/src/style/grid.rs b/src/style/grid.rs index b727bb401..c1147eb0a 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -1052,6 +1052,78 @@ impl MaxTrackSizingFunction { pub fn uses_percentage(self) -> bool { self.0.uses_percentage() } + + /// Expand the compact representation into an [`ExpandedMaxTrackSizingFunction`] enum. + /// + /// This is useful when integrating with other libraries (e.g. for style inspection or + /// serialization) as it allows the value to be pattern-matched without having to work + /// with the raw [`CompactLength`] tagged-pointer representation directly. + pub fn expand(self) -> ExpandedMaxTrackSizingFunction { + match self.0.tag() { + CompactLength::LENGTH_TAG => ExpandedMaxTrackSizingFunction::Length(self.0.value()), + CompactLength::PERCENT_TAG => ExpandedMaxTrackSizingFunction::Percent(self.0.value()), + CompactLength::AUTO_TAG => ExpandedMaxTrackSizingFunction::Auto, + CompactLength::MIN_CONTENT_TAG => ExpandedMaxTrackSizingFunction::MinContent, + CompactLength::MAX_CONTENT_TAG => ExpandedMaxTrackSizingFunction::MaxContent, + CompactLength::FIT_CONTENT_PX_TAG => ExpandedMaxTrackSizingFunction::FitContentPx(self.0.value()), + CompactLength::FIT_CONTENT_PERCENT_TAG => ExpandedMaxTrackSizingFunction::FitContentPercent(self.0.value()), + CompactLength::FR_TAG => ExpandedMaxTrackSizingFunction::Fr(self.0.value()), + #[cfg(feature = "calc")] + _ if self.0.is_calc() => ExpandedMaxTrackSizingFunction::Calc(self.0.calc_value()), + _ => unreachable!("MaxTrackSizingFunction contains a value with an invalid tag"), + } + } +} + +/// The expanded, non-compact representation of a [`MaxTrackSizingFunction`]. +/// +/// Obtained via [`MaxTrackSizingFunction::expand`]. Can be converted back into a +/// [`MaxTrackSizingFunction`] using the [`From`] implementation. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ExpandedMaxTrackSizingFunction { + /// An absolute length (see [`MaxTrackSizingFunction::length`]) + Length(f32), + /// A percentage length (see [`MaxTrackSizingFunction::percent`]) + Percent(f32), + /// The automatic keyword (see [`MaxTrackSizingFunction::auto`]) + Auto, + /// The `min-content` keyword (see [`MaxTrackSizingFunction::min_content`]) + MinContent, + /// The `max-content` keyword (see [`MaxTrackSizingFunction::max_content`]) + MaxContent, + /// A `fit-content(...)` value with a length limit (see [`MaxTrackSizingFunction::fit_content_px`]) + FitContentPx(f32), + /// A `fit-content(...)` value with a percentage limit (see [`MaxTrackSizingFunction::fit_content_percent`]) + FitContentPercent(f32), + /// A fraction of the leftover space (see [`MaxTrackSizingFunction::fr`]) + Fr(f32), + /// A `calc()` value (see [`MaxTrackSizingFunction::calc`]). The pointer is an opaque handle to + /// the calc representation, exactly as passed to the constructor. + #[cfg(feature = "calc")] + Calc(*const ()), +} + +impl From for ExpandedMaxTrackSizingFunction { + fn from(value: MaxTrackSizingFunction) -> Self { + value.expand() + } +} + +impl From for MaxTrackSizingFunction { + fn from(value: ExpandedMaxTrackSizingFunction) -> Self { + match value { + ExpandedMaxTrackSizingFunction::Length(val) => Self::length(val), + ExpandedMaxTrackSizingFunction::Percent(val) => Self::percent(val), + ExpandedMaxTrackSizingFunction::Auto => Self::auto(), + ExpandedMaxTrackSizingFunction::MinContent => Self::min_content(), + ExpandedMaxTrackSizingFunction::MaxContent => Self::max_content(), + ExpandedMaxTrackSizingFunction::FitContentPx(val) => Self::fit_content_px(val), + ExpandedMaxTrackSizingFunction::FitContentPercent(val) => Self::fit_content_percent(val), + ExpandedMaxTrackSizingFunction::Fr(val) => Self::fr(val), + #[cfg(feature = "calc")] + ExpandedMaxTrackSizingFunction::Calc(ptr) => Self::calc(ptr), + } + } } /// Minimum track sizing function @@ -1301,6 +1373,66 @@ impl MinTrackSizingFunction { matches!(self.0.tag(), CompactLength::PERCENT_TAG) } } + + /// Expand the compact representation into an [`ExpandedMinTrackSizingFunction`] enum. + /// + /// This is useful when integrating with other libraries (e.g. for style inspection or + /// serialization) as it allows the value to be pattern-matched without having to work + /// with the raw [`CompactLength`] tagged-pointer representation directly. + pub fn expand(self) -> ExpandedMinTrackSizingFunction { + match self.0.tag() { + CompactLength::LENGTH_TAG => ExpandedMinTrackSizingFunction::Length(self.0.value()), + CompactLength::PERCENT_TAG => ExpandedMinTrackSizingFunction::Percent(self.0.value()), + CompactLength::AUTO_TAG => ExpandedMinTrackSizingFunction::Auto, + CompactLength::MIN_CONTENT_TAG => ExpandedMinTrackSizingFunction::MinContent, + CompactLength::MAX_CONTENT_TAG => ExpandedMinTrackSizingFunction::MaxContent, + #[cfg(feature = "calc")] + _ if self.0.is_calc() => ExpandedMinTrackSizingFunction::Calc(self.0.calc_value()), + _ => unreachable!("MinTrackSizingFunction contains a value with an invalid tag"), + } + } +} + +/// The expanded, non-compact representation of a [`MinTrackSizingFunction`]. +/// +/// Obtained via [`MinTrackSizingFunction::expand`]. Can be converted back into a +/// [`MinTrackSizingFunction`] using the [`From`] implementation. +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ExpandedMinTrackSizingFunction { + /// An absolute length (see [`MinTrackSizingFunction::length`]) + Length(f32), + /// A percentage length (see [`MinTrackSizingFunction::percent`]) + Percent(f32), + /// The automatic keyword (see [`MinTrackSizingFunction::auto`]) + Auto, + /// The `min-content` keyword (see [`MinTrackSizingFunction::min_content`]) + MinContent, + /// The `max-content` keyword (see [`MinTrackSizingFunction::max_content`]) + MaxContent, + /// A `calc()` value (see [`MinTrackSizingFunction::calc`]). The pointer is an opaque handle to + /// the calc representation, exactly as passed to the constructor. + #[cfg(feature = "calc")] + Calc(*const ()), +} + +impl From for ExpandedMinTrackSizingFunction { + fn from(value: MinTrackSizingFunction) -> Self { + value.expand() + } +} + +impl From for MinTrackSizingFunction { + fn from(value: ExpandedMinTrackSizingFunction) -> Self { + match value { + ExpandedMinTrackSizingFunction::Length(val) => Self::length(val), + ExpandedMinTrackSizingFunction::Percent(val) => Self::percent(val), + ExpandedMinTrackSizingFunction::Auto => Self::auto(), + ExpandedMinTrackSizingFunction::MinContent => Self::min_content(), + ExpandedMinTrackSizingFunction::MaxContent => Self::max_content(), + #[cfg(feature = "calc")] + ExpandedMinTrackSizingFunction::Calc(ptr) => Self::calc(ptr), + } + } } /// The sizing function for a grid track (row/column) @@ -1723,3 +1855,64 @@ mod tests { assert_eq!((&repetition).track_count(), u16::MAX); } } + +#[cfg(test)] +mod expand_tests { + use super::*; + + #[test] + fn max_track_sizing_function_round_trips() { + let cases = [ + MaxTrackSizingFunction::length(12.0), + MaxTrackSizingFunction::percent(0.5), + MaxTrackSizingFunction::auto(), + MaxTrackSizingFunction::min_content(), + MaxTrackSizingFunction::max_content(), + MaxTrackSizingFunction::fit_content_px(30.0), + MaxTrackSizingFunction::fit_content_percent(0.75), + MaxTrackSizingFunction::fr(2.0), + ]; + for value in cases { + assert_eq!(MaxTrackSizingFunction::from(value.expand()), value); + assert_eq!(ExpandedMaxTrackSizingFunction::from(value), value.expand()); + } + assert_eq!(MaxTrackSizingFunction::fr(2.0).expand(), ExpandedMaxTrackSizingFunction::Fr(2.0)); + assert_eq!( + MaxTrackSizingFunction::fit_content_px(30.0).expand(), + ExpandedMaxTrackSizingFunction::FitContentPx(30.0) + ); + } + + #[test] + fn min_track_sizing_function_round_trips() { + let cases = [ + MinTrackSizingFunction::length(12.0), + MinTrackSizingFunction::percent(0.5), + MinTrackSizingFunction::auto(), + MinTrackSizingFunction::min_content(), + MinTrackSizingFunction::max_content(), + ]; + for value in cases { + assert_eq!(MinTrackSizingFunction::from(value.expand()), value); + assert_eq!(ExpandedMinTrackSizingFunction::from(value), value.expand()); + } + assert_eq!(MinTrackSizingFunction::max_content().expand(), ExpandedMinTrackSizingFunction::MaxContent); + } + + #[cfg(feature = "calc")] + #[test] + fn track_sizing_function_calc_round_trips() { + #[allow(dead_code)] + #[repr(align(8))] + struct Aligned(u64); + static HANDLE: Aligned = Aligned(0); + let handle = &HANDLE as *const Aligned as *const (); + + assert_eq!(MaxTrackSizingFunction::calc(handle).expand(), ExpandedMaxTrackSizingFunction::Calc(handle)); + assert_eq!( + MaxTrackSizingFunction::from(ExpandedMaxTrackSizingFunction::Calc(handle)), + MaxTrackSizingFunction::calc(handle) + ); + assert_eq!(MinTrackSizingFunction::calc(handle).expand(), ExpandedMinTrackSizingFunction::Calc(handle)); + } +} diff --git a/src/style/mod.rs b/src/style/mod.rs index 5053c08b6..ca91fc524 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -19,7 +19,10 @@ pub use self::alignment::{ }; pub use self::available_space::AvailableSpace; pub use self::compact_length::CompactLength; -pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto}; +pub use self::dimension::{ + Dimension, ExpandedDimension, ExpandedLengthPercentage, ExpandedLengthPercentageAuto, LengthPercentage, + LengthPercentageAuto, +}; use crate::sys::DefaultCheapStr; #[cfg(feature = "block_layout")] @@ -30,9 +33,10 @@ pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItem pub use self::float::{Clear, Float, FloatDirection}; #[cfg(feature = "grid")] pub use self::grid::{ - GenericGridPlacement, GenericGridTemplateComponent, GenericRepetition, GridAutoFlow, GridAutoTracks, - GridContainerStyle, GridItemStyle, GridPlacement, GridTemplateComponent, GridTemplateRepetition, - GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount, TrackSizingFunction, + ExpandedMaxTrackSizingFunction, ExpandedMinTrackSizingFunction, GenericGridPlacement, GenericGridTemplateComponent, + GenericRepetition, GridAutoFlow, GridAutoTracks, GridContainerStyle, GridItemStyle, GridPlacement, + GridTemplateComponent, GridTemplateRepetition, GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, + RepetitionCount, TrackSizingFunction, }; #[cfg(feature = "grid")] pub(crate) use self::grid::{GridAreaAxis, GridAreaEnd};