aura-gui 0.2.2

UI nativa acelerada por GPU para escritorio, Android e iOS, en un solo crate: estilo tipo Tailwind, componentes, sombras, animaciones y agentes de IA. Reposo a cero. Licencia AGPL-3.0 o comercial.
//! Variantes condicionales de Tailwind: puntos de corte (`sm:`, `md:`…) y tema (`dark:`, `light:`).
//!
//! ```ignore
//! div().flex_col().md(|s| s.flex_row().gap_6()).dark(|s| s.bg(slate(900)))
//! ```
//!
//! Los puntos de corte miran el ancho de la ventana en px lógicos y siguen la lógica «primero móvil»: un punto
//! mayor pisa a uno menor. No añaden memoria a quien no los usa (un `Vec` vacío no reserva).

use crate::view::context::ElementContext;
use crate::view::div::Div;
use crate::view::style::Style;

/// Anchos mínimos de Tailwind, en px lógicos.
pub const SM: f32 = 640.0;
pub const MD: f32 = 768.0;
pub const LG: f32 = 1024.0;
pub const XL: f32 = 1280.0;
pub const XXL: f32 = 1536.0;

/// Cuándo se aplica un estilo condicional.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Variant {
    /// La ventana mide al menos este ancho.
    MinWidth(f32),
    /// El tema activo es oscuro.
    Dark,
    /// El tema activo es claro.
    Light,
}

impl Variant {
    pub(crate) fn applies(self, cx: &ElementContext) -> bool {
        match self {
            Variant::MinWidth(width) => cx.viewport().width.0 >= width,
            Variant::Dark => cx.theme.is_dark,
            Variant::Light => !cx.theme.is_dark,
        }
    }
}

impl Div {
    /// Estilo extra desde `width` px de ancho de ventana (`md:`…); varios se aplican de menor a mayor.
    pub fn at_least(mut self, width: f32, refine: impl FnOnce(Style) -> Style) -> Self {
        let variant = Variant::MinWidth(width);
        let at = self.interactivity.variants.partition_point(|(existing, _)| match existing {
            Variant::MinWidth(other) => *other <= width,
            _ => false,
        });
        self.interactivity.variants.insert(at, (variant, refine(Style::default())));
        self
    }

    pub fn sm(self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.at_least(SM, refine)
    }

    pub fn md(self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.at_least(MD, refine)
    }

    pub fn lg(self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.at_least(LG, refine)
    }

    pub fn xl(self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.at_least(XL, refine)
    }

    /// `2xl:`.
    pub fn xxl(self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.at_least(XXL, refine)
    }

    /// Estilo extra con un tema oscuro (`dark:`).
    pub fn dark(mut self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.interactivity.variants.push((Variant::Dark, refine(Style::default())));
        self
    }

    /// Estilo extra con un tema claro.
    pub fn light(mut self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.interactivity.variants.push((Variant::Light, refine(Style::default())));
        self
    }
}