Archived
add el-style, el-layout, el-i18n, el-config, el-secrets: responsive by default, theme-driven, zero breakpoints
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
/// StyleSheet — named style rules for components.
|
||||
///
|
||||
/// Instead of applying modifiers inline everywhere, you can define named
|
||||
/// style rules in a StyleSheet and apply them with `.apply("card")`.
|
||||
/// This is the el-ui equivalent of CSS class names, but type-safe and
|
||||
/// resolved at compile time.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::modifier::StyleSet;
|
||||
|
||||
/// A stylesheet: a named collection of StyleSet rules.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct StyleSheet {
|
||||
rules: HashMap<String, StyleSet>,
|
||||
}
|
||||
|
||||
impl StyleSheet {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Define a named style rule.
|
||||
pub fn define(&mut self, name: impl Into<String>, style: StyleSet) -> &mut Self {
|
||||
self.rules.insert(name.into(), style);
|
||||
self
|
||||
}
|
||||
|
||||
/// Look up a named style rule.
|
||||
/// Returns None if the rule doesn't exist.
|
||||
pub fn get(&self, name: &str) -> Option<&StyleSet> {
|
||||
self.rules.get(name)
|
||||
}
|
||||
|
||||
/// Apply a named style to a StyleSet by merging — caller's explicit
|
||||
/// values win, the stylesheet fills in the rest.
|
||||
///
|
||||
/// This is an additive operation: fields that are Some in the named
|
||||
/// rule overwrite fields that are None in the target.
|
||||
pub fn apply(&self, name: &str, target: &mut StyleSet) {
|
||||
if let Some(rule) = self.rules.get(name) {
|
||||
if target.padding.is_none() {
|
||||
target.padding = rule.padding;
|
||||
}
|
||||
if target.margin.is_none() {
|
||||
target.margin = rule.margin;
|
||||
}
|
||||
if target.background.is_none() {
|
||||
target.background = rule.background.clone();
|
||||
}
|
||||
if target.foreground.is_none() {
|
||||
target.foreground = rule.foreground.clone();
|
||||
}
|
||||
if target.font.is_none() {
|
||||
target.font = rule.font.clone();
|
||||
}
|
||||
if target.radius.is_none() {
|
||||
target.radius = rule.radius;
|
||||
}
|
||||
if target.shadow.is_none() {
|
||||
target.shadow = rule.shadow;
|
||||
}
|
||||
if target.opacity.is_none() {
|
||||
target.opacity = rule.opacity;
|
||||
}
|
||||
if target.border_width.is_none() {
|
||||
target.border_width = rule.border_width;
|
||||
}
|
||||
if target.border_color.is_none() {
|
||||
target.border_color = rule.border_color.clone();
|
||||
}
|
||||
if target.width.is_none() {
|
||||
target.width = rule.width.clone();
|
||||
}
|
||||
if target.height.is_none() {
|
||||
target.height = rule.height.clone();
|
||||
}
|
||||
if target.max_width.is_none() {
|
||||
target.max_width = rule.max_width.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The number of rules defined.
|
||||
pub fn len(&self) -> usize {
|
||||
self.rules.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.rules.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::color::Color;
|
||||
use crate::modifier::StyleSet;
|
||||
|
||||
fn card_style() -> StyleSet {
|
||||
let mut s = StyleSet::default();
|
||||
s.padding = Some([16; 4]);
|
||||
s.radius = Some([8; 4]);
|
||||
s.background = Some(Color::Surface);
|
||||
s
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_define_and_get() {
|
||||
let mut ss = StyleSheet::new();
|
||||
ss.define("card", card_style());
|
||||
assert!(ss.get("card").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_missing_rule_returns_none() {
|
||||
let ss = StyleSheet::new();
|
||||
assert!(ss.get("nonexistent").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_apply_fills_missing_values() {
|
||||
let mut ss = StyleSheet::new();
|
||||
ss.define("card", card_style());
|
||||
|
||||
let mut target = StyleSet::default();
|
||||
ss.apply("card", &mut target);
|
||||
|
||||
assert_eq!(target.padding, Some([16; 4]));
|
||||
assert_eq!(target.background, Some(Color::Surface));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_apply_does_not_overwrite_existing() {
|
||||
let mut ss = StyleSheet::new();
|
||||
ss.define("card", card_style());
|
||||
|
||||
let mut target = StyleSet::default();
|
||||
target.background = Some(Color::Primary); // already set
|
||||
ss.apply("card", &mut target);
|
||||
|
||||
// Should NOT be overwritten by the stylesheet's Surface
|
||||
assert_eq!(target.background, Some(Color::Primary));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_len() {
|
||||
let mut ss = StyleSheet::new();
|
||||
assert_eq!(ss.len(), 0);
|
||||
ss.define("card", card_style());
|
||||
assert_eq!(ss.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stylesheet_apply_nonexistent_is_noop() {
|
||||
let ss = StyleSheet::new();
|
||||
let mut target = StyleSet::default();
|
||||
ss.apply("does-not-exist", &mut target); // should not panic
|
||||
assert!(target.padding.is_none());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user