aura-gui 0.3.5

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.
//! Utilidades de transformación de Tailwind: `rotate_45`, `scale_105`, `translate_x_4`, `neg_translate_y_1_2`,
//! `skew_x_6`. No cambian el layout (el elemento sigue ocupando su sitio) y giran/escalan desde el centro.
//! Se expande dentro de `Styled`.

/// Una utilidad por valor numérico: `rotate_45`, y la versión `neg_` con el signo cambiado.
macro_rules! numbered {
    ($prefix:ident, |$s:ident, $n:ident| $apply:expr; $($value:literal),*) => {
        paste::paste! {
            $(
                fn [<$prefix _ $value>](mut self) -> Self {
                    let $n = $value as f32;
                    let $s = &mut self.style().extra_mut().transform;
                    $apply;
                    self
                }
                fn [<neg_ $prefix _ $value>](mut self) -> Self {
                    let $n = -($value as f32);
                    let $s = &mut self.style().extra_mut().transform;
                    $apply;
                    self
                }
            )*
        }
    };
}

/// `scale-105` = 1,05: el valor de Tailwind está en porcentaje.
macro_rules! percents {
    ($prefix:ident, |$s:ident, $n:ident| $apply:expr; $($value:literal),*) => {
        paste::paste! {
            $(
                fn [<$prefix _ $value>](mut self) -> Self {
                    let $n = $value as f32 / 100.0;
                    let $s = &mut self.style().extra_mut().transform;
                    $apply;
                    self
                }
                fn [<neg_ $prefix _ $value>](mut self) -> Self {
                    let $n = -($value as f32) / 100.0;
                    let $s = &mut self.style().extra_mut().transform;
                    $apply;
                    self
                }
            )*
        }
    };
}

/// `translate-x-1/2`: fracción del propio tamaño, con su versión negativa.
macro_rules! translate_fractions {
    ($($axis:ident),*) => {
        paste::paste! {
            $(
                translate_fraction_steps! { $axis; (1_2, 0.5), (1_3, 1.0 / 3.0), (2_3, 2.0 / 3.0), (1_4, 0.25),
                    (3_4, 0.75), (full, 1.0) }
            )*
        }
    };
}

macro_rules! translate_fraction_steps {
    ($axis:ident; $(($name:tt, $part:expr)),*) => {
        paste::paste! {
            $(
                fn [<translate_ $axis _ $name>](mut self) -> Self {
                    self.style().extra_mut().transform.[<translate_ $axis>] = Some(Length::Percent($part));
                    self
                }
                fn [<neg_translate_ $axis _ $name>](mut self) -> Self {
                    self.style().extra_mut().transform.[<translate_ $axis>] = Some(Length::Percent(-$part));
                    self
                }
            )*
        }
    };
}

macro_rules! transform_utilities {
    () => {
        numbered!(rotate, |t, n| t.rotate = Some(n); 0, 1, 2, 3, 6, 12, 45, 90, 180);
        numbered!(skew_x, |t, n| t.skew_x = Some(n); 0, 1, 2, 3, 6, 12);
        numbered!(skew_y, |t, n| t.skew_y = Some(n); 0, 1, 2, 3, 6, 12);
        percents!(scale_x, |t, n| t.scale_x = Some(n); 0, 50, 75, 90, 95, 100, 105, 110, 125, 150);
        percents!(scale_y, |t, n| t.scale_y = Some(n); 0, 50, 75, 90, 95, 100, 105, 110, 125, 150);
        percents!(scale, |t, n| {
            t.scale_x = Some(n);
            t.scale_y = Some(n);
        }; 0, 50, 75, 90, 95, 100, 105, 110, 125, 150);

        // `translate-x-4` = 16 px; la escala completa de espaciado, también con signo negativo.
        scale_methods!(translate_x, |s, v| s.extra_mut().transform.translate_x = Some(Length::Px(v)));
        scale_methods!(translate_y, |s, v| s.extra_mut().transform.translate_y = Some(Length::Px(v)));
        scale_methods!(neg_translate_x, |s, v| {
            s.extra_mut().transform.translate_x = Some(Length::Px(crate::core::Pixels(-v.0)))
        });
        scale_methods!(neg_translate_y, |s, v| {
            s.extra_mut().transform.translate_y = Some(Length::Px(crate::core::Pixels(-v.0)))
        });
        translate_fractions!(x, y);

        /// `rotate-[37deg]`: grados en sentido horario.
        fn rotate(mut self, degrees: f32) -> Self {
            self.style().extra_mut().transform.rotate = Some(degrees);
            self
        }

        /// `scale-[1.07]`: el mismo factor en los dos ejes (1.0 = tamaño real).
        fn scale(mut self, factor: f32) -> Self {
            let transform = &mut self.style().extra_mut().transform;
            transform.scale_x = Some(factor);
            transform.scale_y = Some(factor);
            self
        }

        fn scale_x(mut self, factor: f32) -> Self {
            self.style().extra_mut().transform.scale_x = Some(factor);
            self
        }

        fn scale_y(mut self, factor: f32) -> Self {
            self.style().extra_mut().transform.scale_y = Some(factor);
            self
        }

        /// `translate-x-[12px]`.
        fn translate_x(mut self, offset: Pixels) -> Self {
            self.style().extra_mut().transform.translate_x = Some(Length::Px(offset));
            self
        }

        fn translate_y(mut self, offset: Pixels) -> Self {
            self.style().extra_mut().transform.translate_y = Some(Length::Px(offset));
            self
        }

        fn skew_x(mut self, degrees: f32) -> Self {
            self.style().extra_mut().transform.skew_x = Some(degrees);
            self
        }

        fn skew_y(mut self, degrees: f32) -> Self {
            self.style().extra_mut().transform.skew_y = Some(degrees);
            self
        }
    };
}

pub(crate) use {numbered, percents, transform_utilities, translate_fraction_steps, translate_fractions};