pub const SP0: f32 = 0.0;
pub const SP0_5: f32 = 2.0;
pub const SP1: f32 = 4.0;
pub const SP2: f32 = 8.0;
pub const SP3: f32 = 12.0;
pub const SP4: f32 = 16.0;
pub const SP5: f32 = 20.0;
pub const SP6: f32 = 24.0;
pub const SP8: f32 = 32.0;
pub const SP10: f32 = 40.0;
pub const SP12: f32 = 48.0;
pub const SP16: f32 = 64.0;
pub const R_SM: f32 = 6.0;
pub const R_MD: f32 = 10.0;
pub const R_LG: f32 = 14.0;
pub const R_XL: f32 = 20.0;
pub const R_FULL: f32 = f32::INFINITY;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum TextSize {
Xs,
Sm,
#[default]
Base,
Lg,
Xl,
Xl2,
Xl3,
}
impl TextSize {
pub const fn px(self) -> f32 {
match self {
Self::Xs => 12.0,
Self::Sm => 14.0,
Self::Base => 16.0,
Self::Lg => 20.0,
Self::Xl => 25.0,
Self::Xl2 => 31.0,
Self::Xl3 => 39.0,
}
}
pub const fn line_height(self) -> f32 {
match self {
Self::Xs | Self::Sm | Self::Base => 1.5,
Self::Lg => 1.4,
Self::Xl | Self::Xl2 => 1.25,
Self::Xl3 => 1.15,
}
}
pub const fn letter_spacing(self) -> f32 {
match self {
Self::Xs | Self::Sm | Self::Base => 0.0,
Self::Lg | Self::Xl => -0.01,
Self::Xl2 | Self::Xl3 => -0.02,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Weight {
#[default]
Regular,
Medium,
Semibold,
}
impl Weight {
pub const fn value(self) -> f32 {
match self {
Self::Regular => 400.0,
Self::Medium => 500.0,
Self::Semibold => 600.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum FamilyRole {
#[default]
Sans,
Mono,
Display,
Serif,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ShadowToken {
Xs,
Sm,
Md,
Lg,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum MotionDuration {
Fast,
#[default]
Base,
Slow,
}
impl MotionDuration {
pub const fn ms(self) -> f32 {
match self {
Self::Fast => 120.0,
Self::Base => 200.0,
Self::Slow => 300.0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CubicBezier {
pub x1: f32,
pub y1: f32,
pub x2: f32,
pub y2: f32,
}
pub const EASE_STANDARD: CubicBezier = CubicBezier {
x1: 0.2,
y1: 0.0,
x2: 0.0,
y2: 1.0,
};
pub const EASE_EXIT: CubicBezier = CubicBezier {
x1: 0.4,
y1: 0.0,
x2: 1.0,
y2: 1.0,
};
#[derive(Debug, Clone, Copy)]
pub struct FocusRing {
pub width: f32,
pub offset: f32,
pub alpha: f32,
}
pub const FOCUS_RING: FocusRing = FocusRing {
width: 2.0,
offset: 2.0,
alpha: 0.6,
};
impl CubicBezier {
pub fn eval(self, x: f32) -> f32 {
if x <= 0.0 {
return 0.0;
}
if x >= 1.0 {
return 1.0;
}
let bez = |t: f32, p1: f32, p2: f32| {
let u = 1.0 - t;
3.0 * u * u * t * p1 + 3.0 * u * t * t * p2 + t * t * t
};
let dbez = |t: f32, p1: f32, p2: f32| {
let u = 1.0 - t;
3.0 * u * u * p1 + 6.0 * u * t * (p2 - p1) + 3.0 * t * t * (1.0 - p2)
};
let mut t = x;
for _ in 0..8 {
let err = bez(t, self.x1, self.x2) - x;
let d = dbez(t, self.x1, self.x2);
if d.abs() < 1e-6 {
break;
}
t = (t - err / d).clamp(0.0, 1.0);
}
bez(t, self.y1, self.y2)
}
}