media queries
This commit is contained in:
parent
78a7799933
commit
0f09a5e22d
25
src/class.rs
25
src/class.rs
|
@ -1,4 +1,8 @@
|
|||
use crate::{Zephyr, ZephyrError};
|
||||
use crate::{
|
||||
media_queries::{ReducedMotion, Responsive},
|
||||
modifiers::Modifiers,
|
||||
Zephyr, ZephyrError,
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub(crate) struct Class<'a> {
|
||||
|
@ -6,7 +10,7 @@ pub(crate) struct Class<'a> {
|
|||
pub value: Option<&'a str>,
|
||||
/// if true, no replacements will be done on `value`
|
||||
pub value_literal: bool,
|
||||
pub modifiers: Vec<&'a str>,
|
||||
pub modifiers: Modifiers<'a>,
|
||||
pub pseudo: Option<&'a str>,
|
||||
/// the original unparsed value
|
||||
/// needed to generate the css selector
|
||||
|
@ -23,7 +27,9 @@ impl<'a> Class<'a> {
|
|||
} = self;
|
||||
|
||||
let mut rest = modifiers
|
||||
.all
|
||||
.iter()
|
||||
.filter(|m| Responsive::from_str(*m).is_none() && ReducedMotion::from_str(*m).is_none())
|
||||
.map(|m| -> &str { z.modifiers.get(*m).map(AsRef::as_ref).unwrap_or(m) })
|
||||
.collect::<Vec<_>>()
|
||||
.join(":");
|
||||
|
@ -56,6 +62,8 @@ impl<'a> Class<'a> {
|
|||
r
|
||||
}
|
||||
|
||||
/// generates the css rule for this class
|
||||
/// does not generate the corresponding media query
|
||||
pub(crate) fn generate(&self, z: &Zephyr) -> Result<String, ZephyrError> {
|
||||
let property = z
|
||||
.properties
|
||||
|
@ -87,4 +95,17 @@ impl<'a> Class<'a> {
|
|||
Err(ZephyrError::ValueMissing)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_with_media_query(&self, z: &Zephyr) -> Result<String, ZephyrError> {
|
||||
let mut css = self.generate(z)?;
|
||||
|
||||
if let Some(r) = &self.modifiers.responsive {
|
||||
css = r.wrap(&css);
|
||||
}
|
||||
if let Some(r) = &self.modifiers.reduced_motion {
|
||||
css = r.wrap(&css);
|
||||
}
|
||||
|
||||
Ok(css)
|
||||
}
|
||||
}
|
||||
|
|
18
src/lib.rs
18
src/lib.rs
|
@ -6,6 +6,8 @@ use crate::{defaults::*, parse::*};
|
|||
|
||||
mod class;
|
||||
mod defaults;
|
||||
mod media_queries;
|
||||
mod modifiers;
|
||||
mod parse;
|
||||
|
||||
#[cfg(feature = "inventory")]
|
||||
|
@ -97,6 +99,8 @@ impl Zephyr {
|
|||
}
|
||||
})
|
||||
// we ignore errors
|
||||
// TODO change this to call parse_class directly
|
||||
// TODO then group by media query
|
||||
.flat_map(|c| match self.generate_class(c) {
|
||||
Ok(v) => Some(v),
|
||||
Err(err) => {
|
||||
|
@ -116,7 +120,7 @@ impl Zephyr {
|
|||
/// this one returns an error if parsing or generating fails
|
||||
pub fn generate_class(&self, class: &str) -> Result<String, ZephyrError> {
|
||||
let c = parse_class(class)?;
|
||||
c.generate(self)
|
||||
c.generate_with_media_query(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,4 +239,16 @@ mod tests {
|
|||
r#".border\{1px_solid_black\}{border:1px_solid_black;}.w\{full\}{width:full;}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_with_media_query() {
|
||||
let z = Zephyr::new();
|
||||
|
||||
// the curly brackets indicate that the value should not go through replacements
|
||||
let classes = z.generate_classes(["m[1rem]sm"]);
|
||||
assert_eq!(
|
||||
classes,
|
||||
r#"@media(min-width:640px){.m\[1rem\]sm{margin:1rem;}}"#
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#[derive(PartialEq, Debug)]
|
||||
pub(crate) enum Responsive {
|
||||
Sm,
|
||||
Md,
|
||||
Lg,
|
||||
Xl,
|
||||
Xxl,
|
||||
}
|
||||
|
||||
impl Responsive {
|
||||
pub fn wrap(&self, css: &str) -> String {
|
||||
match self {
|
||||
Responsive::Sm => wrap_in_query(css, "min-width:640px"),
|
||||
Responsive::Md => wrap_in_query(css, "min-width:768px"),
|
||||
Responsive::Lg => wrap_in_query(css, "min-width:1024px"),
|
||||
Responsive::Xl => wrap_in_query(css, "min-width:1280px"),
|
||||
Responsive::Xxl => wrap_in_query(css, "min-width:1536px"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"sm" => Some(Responsive::Sm),
|
||||
"md" => Some(Responsive::Md),
|
||||
"lg" => Some(Responsive::Lg),
|
||||
"xl" => Some(Responsive::Xl),
|
||||
"xxl" => Some(Responsive::Xxl),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum ReducedMotion {
|
||||
MotionReduce,
|
||||
MotionSafe,
|
||||
}
|
||||
|
||||
impl ReducedMotion {
|
||||
pub fn wrap(&self, css: &str) -> String {
|
||||
match self {
|
||||
Self::MotionReduce => wrap_in_query(css, "prefers-reduced-motion:reduce"),
|
||||
Self::MotionSafe => wrap_in_query(css, "prefers-reduced-motion:no-preference"),
|
||||
}
|
||||
}
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"motion-reduce" => Some(ReducedMotion::MotionReduce),
|
||||
"motion-safe" => Some(ReducedMotion::MotionSafe),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn wrap_in_query(css: &str, query: &str) -> String {
|
||||
format!("@media({query}){{{css}}}")
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
use crate::media_queries::{ReducedMotion, Responsive};
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub(crate) struct Modifiers<'a> {
|
||||
pub all: Vec<&'a str>,
|
||||
pub responsive: Option<Responsive>,
|
||||
pub reduced_motion: Option<ReducedMotion>,
|
||||
}
|
||||
|
||||
impl<'a> Modifiers<'a> {
|
||||
pub(crate) fn new(all: Vec<&'a str>) -> Self {
|
||||
let mut responsive = None;
|
||||
let mut reduced_motion = None;
|
||||
|
||||
for m in &all {
|
||||
responsive = Responsive::from_str(m);
|
||||
reduced_motion = ReducedMotion::from_str(m);
|
||||
}
|
||||
|
||||
Self {
|
||||
all,
|
||||
responsive,
|
||||
reduced_motion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<&'a str>> for Modifiers<'a> {
|
||||
fn from(v: Vec<&'a str>) -> Self {
|
||||
Self::new(v)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue