Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

97
vendor/taffy/src/style/alignment.rs vendored Normal file
View File

@@ -0,0 +1,97 @@
//! Style types for controlling alignment
/// Used to control how child nodes are aligned.
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignItems {
/// Items are packed toward the start of the axis
Start,
/// Items are packed toward the end of the axis
End,
/// Items are packed towards the flex-relative start of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to End. In all other cases it is equivalent to Start.
FlexStart,
/// Items are packed towards the flex-relative end of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to Start. In all other cases it is equivalent to End.
FlexEnd,
/// Items are packed along the center of the cross axis
Center,
/// Items are aligned such as their baselines align
Baseline,
/// Stretch to fill the container
Stretch,
}
/// Used to control how child nodes are aligned.
/// Does not apply to Flexbox, and will be ignored if specified on a flex container
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-items)
pub type JustifyItems = AlignItems;
/// Controls alignment of an individual node
///
/// Overrides the parent Node's `AlignItems` property.
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self)
pub type AlignSelf = AlignItems;
/// Controls alignment of an individual node
///
/// Overrides the parent Node's `JustifyItems` property.
/// Does not apply to Flexbox, and will be ignored if specified on a flex child
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self)
pub type JustifySelf = AlignItems;
/// Sets the distribution of space between and around content items
/// For Flexbox it controls alignment in the cross axis
/// For Grid it controls alignment in the block axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum AlignContent {
/// Items are packed toward the start of the axis
Start,
/// Items are packed toward the end of the axis
End,
/// Items are packed towards the flex-relative start of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to End. In all other cases it is equivalent to Start.
FlexStart,
/// Items are packed towards the flex-relative end of the axis.
///
/// For flex containers with flex_direction RowReverse or ColumnReverse this is equivalent
/// to Start. In all other cases it is equivalent to End.
FlexEnd,
/// Items are centered around the middle of the axis
Center,
/// Items are stretched to fill the container
Stretch,
/// The first and last items are aligned flush with the edges of the container (no gap)
/// The gap between items is distributed evenly.
SpaceBetween,
/// The gap between the first and last items is exactly THE SAME as the gap between items.
/// The gaps are distributed evenly
SpaceEvenly,
/// The gap between the first and last items is exactly HALF the gap between items.
/// The gaps are distributed evenly in proportion to these ratios.
SpaceAround,
}
/// Sets the distribution of space between and around content items
/// For Flexbox it controls alignment in the main axis
/// For Grid it controls alignment in the inline axis
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content)
pub type JustifyContent = AlignContent;

35
vendor/taffy/src/style/block.rs vendored Normal file
View File

@@ -0,0 +1,35 @@
//! Style types for Block layout
use crate::{CoreStyle, Style};
/// The set of styles required for a Block layout container
pub trait BlockContainerStyle: CoreStyle {
/// Defines which row in the grid the item should start and end at
#[inline(always)]
fn text_align(&self) -> TextAlign {
Style::DEFAULT.text_align
}
}
/// The set of styles required for a Block layout item (child of a Block container)
pub trait BlockItemStyle: CoreStyle {
/// Whether the item is a table. Table children are handled specially in block layout.
#[inline(always)]
fn is_table(&self) -> bool {
false
}
}
/// Used by block layout to implement the legacy behaviour of `<center>` and `<div align="left | right | center">`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TextAlign {
/// No special legacy text align behaviour.
#[default]
Auto,
/// Corresponds to `-webkit-left` or `-moz-left` in browsers
LegacyLeft,
/// Corresponds to `-webkit-right` or `-moz-right` in browsers
LegacyRight,
/// Corresponds to `-webkit-center` or `-moz-center` in browsers
LegacyCenter,
}

322
vendor/taffy/src/style/dimension.rs vendored Normal file
View File

@@ -0,0 +1,322 @@
//! Style types for representing lengths / sizes
use crate::geometry::{Rect, Size};
use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyMaxContent, TaffyMinContent, TaffyZero};
use crate::util::sys::abs;
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`].
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum LengthPercentage {
/// An absolute length in some abstract units. Users of Taffy may define what they correspond
/// to in their application (pixels, logical pixels, mm, etc) as they see fit.
Length(f32),
/// A percentage length relative to the size of the containing block.
///
/// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
Percent(f32),
}
impl TaffyZero for LengthPercentage {
const ZERO: Self = Self::Length(0.0);
}
impl FromLength for LengthPercentage {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Length(value.into())
}
}
impl FromPercent for LengthPercentage {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Percent(percent.into())
}
}
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`].
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum LengthPercentageAuto {
/// An absolute length in some abstract units. Users of Taffy may define what they correspond
/// to in their application (pixels, logical pixels, mm, etc) as they see fit.
Length(f32),
/// A percentage length relative to the size of the containing block.
///
/// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
Percent(f32),
/// The dimension should be automatically computed
Auto,
}
impl TaffyZero for LengthPercentageAuto {
const ZERO: Self = Self::Length(0.0);
}
impl TaffyAuto for LengthPercentageAuto {
const AUTO: Self = Self::Auto;
}
impl FromLength for LengthPercentageAuto {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Length(value.into())
}
}
impl FromPercent for LengthPercentageAuto {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Percent(percent.into())
}
}
impl From<LengthPercentage> for LengthPercentageAuto {
fn from(input: LengthPercentage) -> Self {
match input {
LengthPercentage::Length(value) => Self::Length(value),
LengthPercentage::Percent(value) => Self::Percent(value),
}
}
}
impl LengthPercentageAuto {
/// Returns:
/// - Some(length) for Length variants
/// - Some(resolved) using the provided context for Percent variants
/// - None for Auto variants
#[inline(always)]
pub fn resolve_to_option(self, context: f32) -> Option<f32> {
match self {
Self::Length(length) => Some(length),
Self::Percent(percent) => Some(context * percent),
Self::Auto => None,
}
}
/// Returns true if value is LengthPercentageAuto::Auto
#[inline(always)]
pub fn is_auto(self) -> bool {
self == Self::Auto
}
}
/// A unit of linear measurement
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`].
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Dimension {
/// An absolute length in some abstract units. Users of Taffy may define what they correspond
/// to in their application (pixels, logical pixels, mm, etc) as they see fit.
Length(f32),
/// A percentage length relative to the size of the containing block.
///
/// **NOTE: percentages are represented as a f32 value in the range [0.0, 1.0] NOT the range [0.0, 100.0]**
Percent(f32),
/// The dimension should be automatically computed
Auto,
}
impl TaffyZero for Dimension {
const ZERO: Self = Self::Length(0.0);
}
impl TaffyAuto for Dimension {
const AUTO: Self = Self::Auto;
}
impl FromLength for Dimension {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Length(value.into())
}
}
impl FromPercent for Dimension {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Percent(percent.into())
}
}
impl From<LengthPercentage> for Dimension {
fn from(input: LengthPercentage) -> Self {
match input {
LengthPercentage::Length(value) => Self::Length(value),
LengthPercentage::Percent(value) => Self::Percent(value),
}
}
}
impl From<LengthPercentageAuto> for Dimension {
fn from(input: LengthPercentageAuto) -> Self {
match input {
LengthPercentageAuto::Length(value) => Self::Length(value),
LengthPercentageAuto::Percent(value) => Self::Percent(value),
LengthPercentageAuto::Auto => Self::Auto,
}
}
}
impl Dimension {
/// Get Length value if value is Length variant
#[cfg(feature = "grid")]
pub fn into_option(self) -> Option<f32> {
match self {
Dimension::Length(value) => Some(value),
_ => None,
}
}
}
impl Rect<Dimension> {
/// Create a new Rect with [`Dimension::Length`]
#[must_use]
pub const fn from_length(start: f32, end: f32, top: f32, bottom: f32) -> Self {
Rect {
left: Dimension::Length(start),
right: Dimension::Length(end),
top: Dimension::Length(top),
bottom: Dimension::Length(bottom),
}
}
/// Create a new Rect with [`Dimension::Percent`]
#[must_use]
pub const fn from_percent(start: f32, end: f32, top: f32, bottom: f32) -> Self {
Rect {
left: Dimension::Percent(start),
right: Dimension::Percent(end),
top: Dimension::Percent(top),
bottom: Dimension::Percent(bottom),
}
}
}
/// The amount of space available to a node in a given axis
/// <https://www.w3.org/TR/css-sizing-3/#available>
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum AvailableSpace {
/// The amount of space available is the specified number of pixels
Definite(f32),
/// The amount of space available is indefinite and the node should be laid out under a min-content constraint
MinContent,
/// The amount of space available is indefinite and the node should be laid out under a max-content constraint
MaxContent,
}
impl TaffyZero for AvailableSpace {
const ZERO: Self = Self::Definite(0.0);
}
impl TaffyMaxContent for AvailableSpace {
const MAX_CONTENT: Self = Self::MaxContent;
}
impl TaffyMinContent for AvailableSpace {
const MIN_CONTENT: Self = Self::MinContent;
}
impl FromLength for AvailableSpace {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Definite(value.into())
}
}
impl AvailableSpace {
/// Returns true for definite values, else false
pub fn is_definite(self) -> bool {
matches!(self, AvailableSpace::Definite(_))
}
/// Convert to Option
/// Definite values become Some(value). Constraints become None.
pub fn into_option(self) -> Option<f32> {
match self {
AvailableSpace::Definite(value) => Some(value),
_ => None,
}
}
/// Return the definite value or a default value
pub fn unwrap_or(self, default: f32) -> f32 {
self.into_option().unwrap_or(default)
}
/// Return the definite value. Panic is the value is not definite.
#[track_caller]
pub fn unwrap(self) -> f32 {
self.into_option().unwrap()
}
/// Return self if definite or a default value
pub fn or(self, default: AvailableSpace) -> AvailableSpace {
match self {
AvailableSpace::Definite(_) => self,
_ => default,
}
}
/// Return self if definite or a the result of the default value callback
pub fn or_else(self, default_cb: impl FnOnce() -> AvailableSpace) -> AvailableSpace {
match self {
AvailableSpace::Definite(_) => self,
_ => default_cb(),
}
}
/// Return the definite value or the result of the default value callback
pub fn unwrap_or_else(self, default_cb: impl FnOnce() -> f32) -> f32 {
self.into_option().unwrap_or_else(default_cb)
}
/// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
pub fn maybe_set(self, value: Option<f32>) -> AvailableSpace {
match value {
Some(value) => AvailableSpace::Definite(value),
None => self,
}
}
/// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
pub fn map_definite_value(self, map_function: impl FnOnce(f32) -> f32) -> AvailableSpace {
match self {
AvailableSpace::Definite(value) => AvailableSpace::Definite(map_function(value)),
_ => self,
}
}
/// Compute free_space given the passed used_space
pub fn compute_free_space(&self, used_space: f32) -> f32 {
match self {
AvailableSpace::MaxContent => f32::INFINITY,
AvailableSpace::MinContent => 0.0,
AvailableSpace::Definite(available_space) => available_space - used_space,
}
}
/// Compare equality with another AvailableSpace, treating definite values
/// that are within f32::EPSILON of each other as equal
pub fn is_roughly_equal(self, other: AvailableSpace) -> bool {
use AvailableSpace::*;
match (self, other) {
(Definite(a), Definite(b)) => abs(a - b) < f32::EPSILON,
(MinContent, MinContent) => true,
(MaxContent, MaxContent) => true,
_ => false,
}
}
}
impl From<f32> for AvailableSpace {
fn from(value: f32) -> Self {
Self::Definite(value)
}
}
impl From<Option<f32>> for AvailableSpace {
fn from(option: Option<f32>) -> Self {
match option {
Some(value) => Self::Definite(value),
None => Self::MaxContent,
}
}
}
impl Size<AvailableSpace> {
/// Convert `Size<AvailableSpace>` into `Size<Option<f32>>`
pub fn into_options(self) -> Size<Option<f32>> {
Size { width: self.width.into_option(), height: self.height.into_option() }
}
/// If passed value is Some then return AvailableSpace::Definite containing that value, else return self
pub fn maybe_set(self, value: Size<Option<f32>>) -> Size<AvailableSpace> {
Size { width: self.width.maybe_set(value.width), height: self.height.maybe_set(value.height) }
}
}

198
vendor/taffy/src/style/flex.rs vendored Normal file
View File

@@ -0,0 +1,198 @@
//! Style types for Flexbox layout
use super::{AlignContent, AlignItems, AlignSelf, CoreStyle, Dimension, JustifyContent, LengthPercentage, Style};
use crate::geometry::Size;
/// The set of styles required for a Flexbox container
pub trait FlexboxContainerStyle: CoreStyle {
/// Which direction does the main axis flow in?
#[inline(always)]
fn flex_direction(&self) -> FlexDirection {
Style::DEFAULT.flex_direction
}
/// Should elements wrap, or stay in a single line?
#[inline(always)]
fn flex_wrap(&self) -> FlexWrap {
Style::DEFAULT.flex_wrap
}
/// How large should the gaps between items in a grid or flex container be?
#[inline(always)]
fn gap(&self) -> Size<LengthPercentage> {
Style::DEFAULT.gap
}
// Alignment properties
/// How should content contained within this item be aligned in the cross/block axis
#[inline(always)]
fn align_content(&self) -> Option<AlignContent> {
Style::DEFAULT.align_content
}
/// How this node's children aligned in the cross/block axis?
#[inline(always)]
fn align_items(&self) -> Option<AlignItems> {
Style::DEFAULT.align_items
}
/// How this node's children should be aligned in the inline axis
#[inline(always)]
fn justify_content(&self) -> Option<JustifyContent> {
Style::DEFAULT.justify_content
}
}
/// The set of styles required for a Flexbox item (child of a Flexbox container)
pub trait FlexboxItemStyle: CoreStyle {
/// Sets the initial main axis size of the item
#[inline(always)]
fn flex_basis(&self) -> Dimension {
Style::DEFAULT.flex_basis
}
/// The relative rate at which this item grows when it is expanding to fill space
#[inline(always)]
fn flex_grow(&self) -> f32 {
Style::DEFAULT.flex_grow
}
/// The relative rate at which this item shrinks when it is contracting to fit into space
#[inline(always)]
fn flex_shrink(&self) -> f32 {
Style::DEFAULT.flex_shrink
}
/// How this node should be aligned in the cross/block axis
/// Falls back to the parents [`AlignItems`] if not set
#[inline(always)]
fn align_self(&self) -> Option<AlignSelf> {
Style::DEFAULT.align_self
}
}
use crate::geometry::AbsoluteAxis;
/// Controls whether flex items are forced onto one line or can wrap onto multiple lines.
///
/// Defaults to [`FlexWrap::NoWrap`]
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-wrap-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum FlexWrap {
/// Items will not wrap and stay on a single line
NoWrap,
/// Items will wrap according to this item's [`FlexDirection`]
Wrap,
/// Items will wrap in the opposite direction to this item's [`FlexDirection`]
WrapReverse,
}
impl Default for FlexWrap {
fn default() -> Self {
Self::NoWrap
}
}
/// The direction of the flexbox layout main axis.
///
/// There are always two perpendicular layout axes: main (or primary) and cross (or secondary).
/// Adding items will cause them to be positioned adjacent to each other along the main axis.
/// By varying this value throughout your tree, you can create complex axis-aligned layouts.
///
/// Items are always aligned relative to the cross axis, and justified relative to the main axis.
///
/// The default behavior is [`FlexDirection::Row`].
///
/// [Specification](https://www.w3.org/TR/css-flexbox-1/#flex-direction-property)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum FlexDirection {
/// Defines +x as the main axis
///
/// Items will be added from left to right in a row.
Row,
/// Defines +y as the main axis
///
/// Items will be added from top to bottom in a column.
Column,
/// Defines -x as the main axis
///
/// Items will be added from right to left in a row.
RowReverse,
/// Defines -y as the main axis
///
/// Items will be added from bottom to top in a column.
ColumnReverse,
}
impl Default for FlexDirection {
fn default() -> Self {
Self::Row
}
}
impl FlexDirection {
#[inline]
/// Is the direction [`FlexDirection::Row`] or [`FlexDirection::RowReverse`]?
pub(crate) fn is_row(self) -> bool {
matches!(self, Self::Row | Self::RowReverse)
}
#[inline]
/// Is the direction [`FlexDirection::Column`] or [`FlexDirection::ColumnReverse`]?
pub(crate) fn is_column(self) -> bool {
matches!(self, Self::Column | Self::ColumnReverse)
}
#[inline]
/// Is the direction [`FlexDirection::RowReverse`] or [`FlexDirection::ColumnReverse`]?
pub(crate) fn is_reverse(self) -> bool {
matches!(self, Self::RowReverse | Self::ColumnReverse)
}
#[inline]
/// The `AbsoluteAxis` that corresponds to the main axis
pub(crate) fn main_axis(self) -> AbsoluteAxis {
match self {
Self::Row | Self::RowReverse => AbsoluteAxis::Horizontal,
Self::Column | Self::ColumnReverse => AbsoluteAxis::Vertical,
}
}
#[inline]
/// The `AbsoluteAxis` that corresponds to the cross axis
pub(crate) fn cross_axis(self) -> AbsoluteAxis {
match self {
Self::Row | Self::RowReverse => AbsoluteAxis::Vertical,
Self::Column | Self::ColumnReverse => AbsoluteAxis::Horizontal,
}
}
}
#[cfg(test)]
mod tests {
mod test_flex_direction {
use crate::style::*;
#[test]
fn flex_direction_is_row() {
assert!(FlexDirection::Row.is_row());
assert!(FlexDirection::RowReverse.is_row());
assert!(!FlexDirection::Column.is_row());
assert!(!FlexDirection::ColumnReverse.is_row());
}
#[test]
fn flex_direction_is_column() {
assert!(!FlexDirection::Row.is_column());
assert!(!FlexDirection::RowReverse.is_column());
assert!(FlexDirection::Column.is_column());
assert!(FlexDirection::ColumnReverse.is_column());
}
#[test]
fn flex_direction_is_reverse() {
assert!(!FlexDirection::Row.is_reverse());
assert!(FlexDirection::RowReverse.is_reverse());
assert!(!FlexDirection::Column.is_reverse());
assert!(FlexDirection::ColumnReverse.is_reverse());
}
}
}

716
vendor/taffy/src/style/grid.rs vendored Normal file
View File

@@ -0,0 +1,716 @@
//! Style types for CSS Grid layout
use super::{AlignContent, AlignItems, AlignSelf, CoreStyle, JustifyContent, LengthPercentage, Style};
use crate::compute::grid::{GridCoordinate, GridLine, OriginZeroLine};
use crate::geometry::{AbsoluteAxis, AbstractAxis, Line, MinMax, Size};
use crate::style_helpers::*;
use crate::util::sys::GridTrackVec;
use core::borrow::Borrow;
use core::cmp::{max, min};
use core::convert::Infallible;
/// The set of styles required for a CSS Grid container
pub trait GridContainerStyle: CoreStyle {
/// The type returned by grid_template_rows and grid_template_columns
type TemplateTrackList<'a>: Borrow<[TrackSizingFunction]>
where
Self: 'a;
/// The type returned by grid_auto_rows and grid_auto_columns
type AutoTrackList<'a>: Borrow<[NonRepeatedTrackSizingFunction]>
where
Self: 'a;
// FIXME: re-add default implemenations for grid_{template,auto}_{rows,columns} once the
// associated_type_defaults feature (https://github.com/rust-lang/rust/issues/29661) is stabilised.
/// Defines the track sizing functions (heights) of the grid rows
fn grid_template_rows(&self) -> Self::TemplateTrackList<'_>;
/// Defines the track sizing functions (widths) of the grid columns
fn grid_template_columns(&self) -> Self::TemplateTrackList<'_>;
/// Defines the size of implicitly created rows
fn grid_auto_rows(&self) -> Self::AutoTrackList<'_>;
/// Defined the size of implicitly created columns
fn grid_auto_columns(&self) -> Self::AutoTrackList<'_>;
/// Controls how items get placed into the grid for auto-placed items
#[inline(always)]
fn grid_auto_flow(&self) -> GridAutoFlow {
Style::DEFAULT.grid_auto_flow
}
/// How large should the gaps between items in a grid or flex container be?
#[inline(always)]
fn gap(&self) -> Size<LengthPercentage> {
Style::DEFAULT.gap
}
// Alignment properties
/// How should content contained within this item be aligned in the cross/block axis
#[inline(always)]
fn align_content(&self) -> Option<AlignContent> {
Style::DEFAULT.align_content
}
/// How should contained within this item be aligned in the main/inline axis
#[inline(always)]
fn justify_content(&self) -> Option<JustifyContent> {
Style::DEFAULT.justify_content
}
/// How this node's children aligned in the cross/block axis?
#[inline(always)]
fn align_items(&self) -> Option<AlignItems> {
Style::DEFAULT.align_items
}
/// How this node's children should be aligned in the inline axis
#[inline(always)]
fn justify_items(&self) -> Option<AlignItems> {
Style::DEFAULT.justify_items
}
/// Get a grid item's row or column placement depending on the axis passed
#[inline(always)]
fn grid_template_tracks(&self, axis: AbsoluteAxis) -> Self::TemplateTrackList<'_> {
match axis {
AbsoluteAxis::Horizontal => self.grid_template_columns(),
AbsoluteAxis::Vertical => self.grid_template_rows(),
}
}
/// Get a grid container's align-content or justify-content alignment depending on the axis passed
#[inline(always)]
fn grid_align_content(&self, axis: AbstractAxis) -> AlignContent {
match axis {
AbstractAxis::Inline => self.justify_content().unwrap_or(AlignContent::Stretch),
AbstractAxis::Block => self.align_content().unwrap_or(AlignContent::Stretch),
}
}
}
/// The set of styles required for a CSS Grid item (child of a CSS Grid container)
pub trait GridItemStyle: CoreStyle {
/// Defines which row in the grid the item should start and end at
#[inline(always)]
fn grid_row(&self) -> Line<GridPlacement> {
Style::DEFAULT.grid_row
}
/// Defines which column in the grid the item should start and end at
#[inline(always)]
fn grid_column(&self) -> Line<GridPlacement> {
Style::DEFAULT.grid_column
}
/// How this node should be aligned in the cross/block axis
/// Falls back to the parents [`AlignItems`] if not set
#[inline(always)]
fn align_self(&self) -> Option<AlignSelf> {
Style::DEFAULT.align_self
}
/// How this node should be aligned in the inline axis
/// Falls back to the parents [`super::JustifyItems`] if not set
#[inline(always)]
fn justify_self(&self) -> Option<AlignSelf> {
Style::DEFAULT.justify_self
}
/// Get a grid item's row or column placement depending on the axis passed
#[inline(always)]
fn grid_placement(&self, axis: AbsoluteAxis) -> Line<GridPlacement> {
match axis {
AbsoluteAxis::Horizontal => self.grid_column(),
AbsoluteAxis::Vertical => self.grid_row(),
}
}
}
/// Controls whether grid items are placed row-wise or column-wise. And whether the sparse or dense packing algorithm is used.
///
/// The "dense" packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.
///
/// Defaults to [`GridAutoFlow::Row`]
///
/// [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow)
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum GridAutoFlow {
/// Items are placed by filling each row in turn, adding new rows as necessary
Row,
/// Items are placed by filling each column in turn, adding new columns as necessary.
Column,
/// Combines `Row` with the dense packing algorithm.
RowDense,
/// Combines `Column` with the dense packing algorithm.
ColumnDense,
}
impl Default for GridAutoFlow {
fn default() -> Self {
Self::Row
}
}
impl GridAutoFlow {
/// Whether grid auto placement uses the sparse placement algorithm or the dense placement algorithm
/// See: <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow#values>
pub fn is_dense(&self) -> bool {
match self {
Self::Row | Self::Column => false,
Self::RowDense | Self::ColumnDense => true,
}
}
/// Whether grid auto placement fills areas row-wise or column-wise
/// See: <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow#values>
pub fn primary_axis(&self) -> AbsoluteAxis {
match self {
Self::Row | Self::RowDense => AbsoluteAxis::Horizontal,
Self::Column | Self::ColumnDense => AbsoluteAxis::Vertical,
}
}
}
/// A grid line placement specification which is generic over the coordinate system that it uses to define
/// grid line positions.
///
/// GenericGridPlacement<GridLine> is aliased as GridPlacement and is exposed to users of Taffy to define styles.
/// GenericGridPlacement<OriginZeroLine> is aliased as OriginZeroGridPlacement and is used internally for placement computations.
///
/// See [`crate::compute::grid::type::coordinates`] for documentation on the different coordinate systems.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum GenericGridPlacement<LineType: GridCoordinate> {
/// Place item according to the auto-placement algorithm, and the parent's grid_auto_flow property
Auto,
/// Place item at specified line (column or row) index
Line(LineType),
/// Item should span specified number of tracks (columns or rows)
Span(u16),
}
/// A grid line placement using the normalized OriginZero coordinates to specify line positions.
pub(crate) type OriginZeroGridPlacement = GenericGridPlacement<OriginZeroLine>;
/// A grid line placement specification. Used for grid-[row/column]-[start/end]. Named tracks are not implemented.
///
/// Defaults to `GridPlacement::Auto`
///
/// [Specification](https://www.w3.org/TR/css3-grid-layout/#typedef-grid-row-start-grid-line)
pub type GridPlacement = GenericGridPlacement<GridLine>;
impl TaffyAuto for GridPlacement {
const AUTO: Self = Self::Auto;
}
impl TaffyGridLine for GridPlacement {
fn from_line_index(index: i16) -> Self {
GridPlacement::Line(GridLine::from(index))
}
}
impl TaffyGridLine for Line<GridPlacement> {
fn from_line_index(index: i16) -> Self {
Line { start: GridPlacement::from_line_index(index), end: GridPlacement::Auto }
}
}
impl TaffyGridSpan for GridPlacement {
fn from_span(span: u16) -> Self {
GridPlacement::Span(span)
}
}
impl TaffyGridSpan for Line<GridPlacement> {
fn from_span(span: u16) -> Self {
Line { start: GridPlacement::from_span(span), end: GridPlacement::Auto }
}
}
impl Default for GridPlacement {
fn default() -> Self {
Self::Auto
}
}
impl GridPlacement {
/// Apply a mapping function if the [`GridPlacement`] is a `Track`. Otherwise return `self` unmodified.
pub fn into_origin_zero_placement(self, explicit_track_count: u16) -> OriginZeroGridPlacement {
match self {
Self::Auto => OriginZeroGridPlacement::Auto,
Self::Span(span) => OriginZeroGridPlacement::Span(span),
// Grid line zero is an invalid index, so it gets treated as Auto
// See: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row-start#values
Self::Line(line) => match line.as_i16() {
0 => OriginZeroGridPlacement::Auto,
_ => OriginZeroGridPlacement::Line(line.into_origin_zero_line(explicit_track_count)),
},
}
}
}
impl<T: GridCoordinate> Line<GenericGridPlacement<T>> {
/// Resolves the span for an indefinite placement (a placement that does not consist of two `Track`s).
/// Panics if called on a definite placement
pub fn indefinite_span(&self) -> u16 {
use GenericGridPlacement as GP;
match (self.start, self.end) {
(GP::Line(_), GP::Auto) => 1,
(GP::Auto, GP::Line(_)) => 1,
(GP::Auto, GP::Auto) => 1,
(GP::Line(_), GP::Span(span)) => span,
(GP::Span(span), GP::Line(_)) => span,
(GP::Span(span), GP::Auto) => span,
(GP::Auto, GP::Span(span)) => span,
(GP::Span(span), GP::Span(_)) => span,
(GP::Line(_), GP::Line(_)) => panic!("indefinite_span should only be called on indefinite grid tracks"),
}
}
}
impl Line<GridPlacement> {
#[inline]
/// Whether the track position is definite in this axis (or the item will need auto placement)
/// The track position is definite if least one of the start and end positions is a NON-ZERO track index
/// (0 is an invalid line in GridLine coordinates, and falls back to "auto" which is indefinite)
pub fn is_definite(&self) -> bool {
match (self.start, self.end) {
(GenericGridPlacement::Line(line), _) if line.as_i16() != 0 => true,
(_, GenericGridPlacement::Line(line)) if line.as_i16() != 0 => true,
_ => false,
}
}
/// Apply a mapping function if the [`GridPlacement`] is a `Track`. Otherwise return `self` unmodified.
pub fn into_origin_zero(&self, explicit_track_count: u16) -> Line<OriginZeroGridPlacement> {
Line {
start: self.start.into_origin_zero_placement(explicit_track_count),
end: self.end.into_origin_zero_placement(explicit_track_count),
}
}
}
impl Line<OriginZeroGridPlacement> {
#[inline]
/// Whether the track position is definite in this axis (or the item will need auto placement)
/// The track position is definite if least one of the start and end positions is a track index
pub fn is_definite(&self) -> bool {
matches!((self.start, self.end), (GenericGridPlacement::Line(_), _) | (_, GenericGridPlacement::Line(_)))
}
/// If at least one of the of the start and end positions is a track index then the other end can be resolved
/// into a track index purely based on the information contained with the placement specification
pub fn resolve_definite_grid_lines(&self) -> Line<OriginZeroLine> {
use OriginZeroGridPlacement as GP;
match (self.start, self.end) {
(GP::Line(line1), GP::Line(line2)) => {
if line1 == line2 {
Line { start: line1, end: line1 + 1 }
} else {
Line { start: min(line1, line2), end: max(line1, line2) }
}
}
(GP::Line(line), GP::Span(span)) => Line { start: line, end: line + span },
(GP::Line(line), GP::Auto) => Line { start: line, end: line + 1 },
(GP::Span(span), GP::Line(line)) => Line { start: line - span, end: line },
(GP::Auto, GP::Line(line)) => Line { start: line - 1, end: line },
_ => panic!("resolve_definite_grid_tracks should only be called on definite grid tracks"),
}
}
/// For absolutely positioned items:
/// - Tracks resolve to definite tracks
/// - For Spans:
/// - If the other position is a Track, they resolve to a definite track relative to the other track
/// - Else resolve to None
/// - Auto resolves to None
///
/// When finally positioning the item, a value of None means that the item's grid area is bounded by the grid
/// container's border box on that side.
pub fn resolve_absolutely_positioned_grid_tracks(&self) -> Line<Option<OriginZeroLine>> {
use OriginZeroGridPlacement as GP;
match (self.start, self.end) {
(GP::Line(track1), GP::Line(track2)) => {
if track1 == track2 {
Line { start: Some(track1), end: Some(track1 + 1) }
} else {
Line { start: Some(min(track1, track2)), end: Some(max(track1, track2)) }
}
}
(GP::Line(track), GP::Span(span)) => Line { start: Some(track), end: Some(track + span) },
(GP::Line(track), GP::Auto) => Line { start: Some(track), end: None },
(GP::Span(span), GP::Line(track)) => Line { start: Some(track - span), end: Some(track) },
(GP::Auto, GP::Line(track)) => Line { start: None, end: Some(track) },
_ => Line { start: None, end: None },
}
}
/// If neither of the start and end positions is a track index then the other end can be resolved
/// into a track index if a definite start position is supplied externally
pub fn resolve_indefinite_grid_tracks(&self, start: OriginZeroLine) -> Line<OriginZeroLine> {
use OriginZeroGridPlacement as GP;
match (self.start, self.end) {
(GP::Auto, GP::Auto) => Line { start, end: start + 1 },
(GP::Span(span), GP::Auto) => Line { start, end: start + span },
(GP::Auto, GP::Span(span)) => Line { start, end: start + span },
(GP::Span(span), GP::Span(_)) => Line { start, end: start + span },
_ => panic!("resolve_indefinite_grid_tracks should only be called on indefinite grid tracks"),
}
}
}
/// Represents the start and end points of a GridItem within a given axis
impl Default for Line<GridPlacement> {
fn default() -> Self {
Line { start: GridPlacement::Auto, end: GridPlacement::Auto }
}
}
/// Maximum track sizing function
///
/// Specifies the maximum size of a grid track. A grid track will automatically size between it's minimum and maximum size based
/// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under.
/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum MaxTrackSizingFunction {
/// Track maximum size should be a fixed length or percentage value
Fixed(LengthPercentage),
/// Track maximum size should be content sized under a min-content constraint
MinContent,
/// Track maximum size should be content sized under a max-content constraint
MaxContent,
/// Track maximum size should be sized according to the fit-content formula
FitContent(LengthPercentage),
/// Track maximum size should be automatically sized
Auto,
/// The dimension as a fraction of the total available grid space (`fr` units in CSS)
/// Specified value is the numerator of the fraction. Denominator is the sum of all fraction specified in that grid dimension
/// Spec: <https://www.w3.org/TR/css3-grid-layout/#fr-unit>
Fraction(f32),
}
impl TaffyAuto for MaxTrackSizingFunction {
const AUTO: Self = Self::Auto;
}
impl TaffyMinContent for MaxTrackSizingFunction {
const MIN_CONTENT: Self = Self::MinContent;
}
impl TaffyMaxContent for MaxTrackSizingFunction {
const MAX_CONTENT: Self = Self::MaxContent;
}
impl TaffyFitContent for MaxTrackSizingFunction {
fn fit_content(argument: LengthPercentage) -> Self {
Self::FitContent(argument)
}
}
impl TaffyZero for MaxTrackSizingFunction {
const ZERO: Self = Self::Fixed(LengthPercentage::ZERO);
}
impl FromLength for MaxTrackSizingFunction {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Fixed(LengthPercentage::from_length(value))
}
}
impl FromPercent for MaxTrackSizingFunction {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Fixed(LengthPercentage::from_percent(percent))
}
}
impl FromFlex for MaxTrackSizingFunction {
fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self {
Self::Fraction(flex.into())
}
}
impl MaxTrackSizingFunction {
/// Returns true if the max track sizing function is `MinContent`, `MaxContent`, `FitContent` or `Auto`, else false.
#[inline(always)]
pub fn is_intrinsic(&self) -> bool {
matches!(self, Self::MinContent | Self::MaxContent | Self::FitContent(_) | Self::Auto)
}
/// Returns true if the max track sizing function is `MaxContent`, `FitContent` or `Auto` else false.
/// "In all cases, treat auto and fit-content() as max-content, except where specified otherwise for fit-content()."
/// See: <https://www.w3.org/TR/css-grid-1/#algo-terms>
#[inline(always)]
pub fn is_max_content_alike(&self) -> bool {
matches!(self, Self::MaxContent | Self::FitContent(_) | Self::Auto)
}
/// Returns true if the max track sizing function is `Flex`, else false.
#[inline(always)]
pub fn is_flexible(&self) -> bool {
matches!(self, Self::Fraction(_))
}
/// Returns fixed point values directly. Attempts to resolve percentage values against
/// the passed available_space and returns if this results in a concrete value (which it
/// will if the available_space is `Some`). Otherwise returns None.
#[inline(always)]
pub fn definite_value(self, parent_size: Option<f32>) -> Option<f32> {
use MaxTrackSizingFunction::*;
match self {
Fixed(LengthPercentage::Length(size)) => Some(size),
Fixed(LengthPercentage::Percent(fraction)) => parent_size.map(|size| fraction * size),
MinContent | MaxContent | FitContent(_) | Auto | Fraction(_) => None,
}
}
/// Resolve the maximum size of the track as defined by either:
/// - A fixed track sizing function
/// - A percentage track sizing function (with definite available space)
/// - A fit-content sizing function with fixed argument
/// - A fit-content sizing function with percentage argument (with definite available space)
/// All other kinds of track sizing function return None.
#[inline(always)]
pub fn definite_limit(self, parent_size: Option<f32>) -> Option<f32> {
use MaxTrackSizingFunction::FitContent;
match self {
FitContent(LengthPercentage::Length(size)) => Some(size),
FitContent(LengthPercentage::Percent(fraction)) => parent_size.map(|size| fraction * size),
_ => self.definite_value(parent_size),
}
}
/// Resolve percentage values against the passed parent_size, returning Some(value)
/// Non-percentage values always return None.
#[inline(always)]
pub fn resolved_percentage_size(self, parent_size: f32) -> Option<f32> {
use MaxTrackSizingFunction::*;
match self {
Fixed(LengthPercentage::Percent(fraction)) => Some(fraction * parent_size),
Fixed(LengthPercentage::Length(_)) | MinContent | MaxContent | FitContent(_) | Auto | Fraction(_) => None,
}
}
/// Whether the track sizing functions depends on the size of the parent node
#[inline(always)]
pub fn uses_percentage(self) -> bool {
use MaxTrackSizingFunction::*;
matches!(self, Fixed(LengthPercentage::Percent(_)) | FitContent(LengthPercentage::Percent(_)))
}
}
/// Minimum track sizing function
///
/// Specifies the minimum size of a grid track. A grid track will automatically size between it's minimum and maximum size based
/// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under.
/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
#[derive(Copy, Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum MinTrackSizingFunction {
/// Track minimum size should be a fixed length or percentage value
Fixed(LengthPercentage),
/// Track minimum size should be content sized under a min-content constraint
MinContent,
/// Track minimum size should be content sized under a max-content constraint
MaxContent,
/// Track minimum size should be automatically sized
Auto,
}
impl TaffyAuto for MinTrackSizingFunction {
const AUTO: Self = Self::Auto;
}
impl TaffyMinContent for MinTrackSizingFunction {
const MIN_CONTENT: Self = Self::MinContent;
}
impl TaffyMaxContent for MinTrackSizingFunction {
const MAX_CONTENT: Self = Self::MaxContent;
}
impl TaffyZero for MinTrackSizingFunction {
const ZERO: Self = Self::Fixed(LengthPercentage::ZERO);
}
impl FromLength for MinTrackSizingFunction {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Fixed(LengthPercentage::from_length(value))
}
}
impl FromPercent for MinTrackSizingFunction {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Fixed(LengthPercentage::from_percent(percent))
}
}
impl MinTrackSizingFunction {
/// Returns true if the min track sizing function is `MinContent`, `MaxContent` or `Auto`, else false.
#[inline(always)]
pub fn is_intrinsic(&self) -> bool {
matches!(self, Self::MinContent | Self::MaxContent | Self::Auto)
}
/// Returns fixed point values directly. Attempts to resolve percentage values against
/// the passed available_space and returns if this results in a concrete value (which it
/// will if the available_space is `Some`). Otherwise returns `None`.
#[inline(always)]
pub fn definite_value(self, parent_size: Option<f32>) -> Option<f32> {
use MinTrackSizingFunction::*;
match self {
Fixed(LengthPercentage::Length(size)) => Some(size),
Fixed(LengthPercentage::Percent(fraction)) => parent_size.map(|size| fraction * size),
MinContent | MaxContent | Auto => None,
}
}
/// Resolve percentage values against the passed parent_size, returning Some(value)
/// Non-percentage values always return None.
#[inline(always)]
pub fn resolved_percentage_size(self, parent_size: f32) -> Option<f32> {
use MinTrackSizingFunction::*;
match self {
Fixed(LengthPercentage::Percent(fraction)) => Some(fraction * parent_size),
Fixed(LengthPercentage::Length(_)) | MinContent | MaxContent | Auto => None,
}
}
/// Whether the track sizing functions depends on the size of the parent node
#[inline(always)]
pub fn uses_percentage(self) -> bool {
use MinTrackSizingFunction::*;
matches!(self, Fixed(LengthPercentage::Percent(_)))
}
}
/// The sizing function for a grid track (row/column)
///
/// May either be a MinMax variant which specifies separate values for the min-/max- track sizing functions
/// or a scalar value which applies to both track sizing functions.
pub type NonRepeatedTrackSizingFunction = MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>;
impl NonRepeatedTrackSizingFunction {
/// Extract the min track sizing function
pub fn min_sizing_function(&self) -> MinTrackSizingFunction {
self.min
}
/// Extract the max track sizing function
pub fn max_sizing_function(&self) -> MaxTrackSizingFunction {
self.max
}
/// Determine whether at least one of the components ("min" and "max") are fixed sizing function
pub fn has_fixed_component(&self) -> bool {
matches!(self.min, MinTrackSizingFunction::Fixed(_)) || matches!(self.max, MaxTrackSizingFunction::Fixed(_))
}
}
impl TaffyAuto for NonRepeatedTrackSizingFunction {
const AUTO: Self = Self { min: MinTrackSizingFunction::AUTO, max: MaxTrackSizingFunction::AUTO };
}
impl TaffyMinContent for NonRepeatedTrackSizingFunction {
const MIN_CONTENT: Self =
Self { min: MinTrackSizingFunction::MIN_CONTENT, max: MaxTrackSizingFunction::MIN_CONTENT };
}
impl TaffyMaxContent for NonRepeatedTrackSizingFunction {
const MAX_CONTENT: Self =
Self { min: MinTrackSizingFunction::MAX_CONTENT, max: MaxTrackSizingFunction::MAX_CONTENT };
}
impl TaffyFitContent for NonRepeatedTrackSizingFunction {
fn fit_content(argument: LengthPercentage) -> Self {
Self { min: MinTrackSizingFunction::AUTO, max: MaxTrackSizingFunction::FitContent(argument) }
}
}
impl TaffyZero for NonRepeatedTrackSizingFunction {
const ZERO: Self = Self { min: MinTrackSizingFunction::ZERO, max: MaxTrackSizingFunction::ZERO };
}
impl FromLength for NonRepeatedTrackSizingFunction {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self { min: MinTrackSizingFunction::from_length(value), max: MaxTrackSizingFunction::from_length(value) }
}
}
impl FromPercent for NonRepeatedTrackSizingFunction {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self { min: MinTrackSizingFunction::from_percent(percent), max: MaxTrackSizingFunction::from_percent(percent) }
}
}
impl FromFlex for NonRepeatedTrackSizingFunction {
fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self {
Self { min: MinTrackSizingFunction::AUTO, max: MaxTrackSizingFunction::from_flex(flex) }
}
}
/// The first argument to a repeated track definition. This type represents the type of automatic repetition to perform.
///
/// See <https://www.w3.org/TR/css-grid-1/#auto-repeat> for an explanation of how auto-repeated track definitions work
/// and the difference between AutoFit and AutoFill.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum GridTrackRepetition {
/// Auto-repeating tracks should be generated to fit the container
/// See: <https://developer.mozilla.org/en-US/docs/Web/CSS/repeat#auto-fill>
AutoFill,
/// Auto-repeating tracks should be generated to fit the container
/// See: <https://developer.mozilla.org/en-US/docs/Web/CSS/repeat#auto-fit>
AutoFit,
/// The specified tracks should be repeated exacts N times
Count(u16),
}
impl TryFrom<u16> for GridTrackRepetition {
type Error = Infallible;
fn try_from(value: u16) -> Result<Self, Infallible> {
Ok(Self::Count(value))
}
}
/// Error returned when trying to convert a string to a GridTrackRepetition and that string is not
/// either "auto-fit" or "auto-fill"
#[derive(Debug)]
pub struct InvalidStringRepetitionValue;
#[cfg(feature = "std")]
impl std::error::Error for InvalidStringRepetitionValue {}
impl core::fmt::Display for InvalidStringRepetitionValue {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("&str can only be converted to GridTrackRepetition if it's value is 'auto-fit' or 'auto-fill'")
}
}
impl TryFrom<&str> for GridTrackRepetition {
type Error = InvalidStringRepetitionValue;
fn try_from(value: &str) -> Result<Self, InvalidStringRepetitionValue> {
match value {
"auto-fit" => Ok(Self::AutoFit),
"auto-fill" => Ok(Self::AutoFill),
_ => Err(InvalidStringRepetitionValue),
}
}
}
/// The sizing function for a grid track (row/column)
/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TrackSizingFunction {
/// A single non-repeated track
Single(NonRepeatedTrackSizingFunction),
/// Automatically generate grid tracks to fit the available space using the specified definite track lengths
/// Only valid if every track in template (not just the repetition) has a fixed size.
Repeat(GridTrackRepetition, GridTrackVec<NonRepeatedTrackSizingFunction>),
}
impl TrackSizingFunction {
/// Whether the track definition is a auto-repeated fragment
pub fn is_auto_repetition(&self) -> bool {
matches!(self, Self::Repeat(GridTrackRepetition::AutoFit | GridTrackRepetition::AutoFill, _))
}
}
impl TaffyAuto for TrackSizingFunction {
const AUTO: Self = Self::Single(NonRepeatedTrackSizingFunction::AUTO);
}
impl TaffyMinContent for TrackSizingFunction {
const MIN_CONTENT: Self = Self::Single(NonRepeatedTrackSizingFunction::MIN_CONTENT);
}
impl TaffyMaxContent for TrackSizingFunction {
const MAX_CONTENT: Self = Self::Single(NonRepeatedTrackSizingFunction::MAX_CONTENT);
}
impl TaffyFitContent for TrackSizingFunction {
fn fit_content(argument: LengthPercentage) -> Self {
Self::Single(NonRepeatedTrackSizingFunction::fit_content(argument))
}
}
impl TaffyZero for TrackSizingFunction {
const ZERO: Self = Self::Single(NonRepeatedTrackSizingFunction::ZERO);
}
impl FromLength for TrackSizingFunction {
fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
Self::Single(NonRepeatedTrackSizingFunction::from_length(value))
}
}
impl FromPercent for TrackSizingFunction {
fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
Self::Single(NonRepeatedTrackSizingFunction::from_percent(percent))
}
}
impl FromFlex for TrackSizingFunction {
fn from_flex<Input: Into<f32> + Copy>(flex: Input) -> Self {
Self::Single(NonRepeatedTrackSizingFunction::from_flex(flex))
}
}
impl From<MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>> for TrackSizingFunction {
fn from(input: MinMax<MinTrackSizingFunction, MaxTrackSizingFunction>) -> Self {
Self::Single(input)
}
}

1061
vendor/taffy/src/style/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff