⚰️ Simplify class handling
This commit is contained in:
parent
6dd9eb28f5
commit
80139d9153
11 changed files with 47 additions and 80 deletions
|
|
@ -74,14 +74,11 @@ impl ThemeTrait for Bulmix {
|
|||
}
|
||||
_ => {}
|
||||
};
|
||||
match a.anchor_type() {
|
||||
AnchorType::Button => {
|
||||
a.alter_classes(
|
||||
ClassesOp::Replace(a.anchor_type().to_string()),
|
||||
"button is-primary",
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
if let AnchorType::Button = a.anchor_type() {
|
||||
a.alter_classes(
|
||||
ClassesOp::Replace(a.anchor_type().to_string()),
|
||||
"button is-primary",
|
||||
);
|
||||
};
|
||||
}
|
||||
COMPONENT_BASE_HEADING => {
|
||||
|
|
@ -90,12 +87,12 @@ impl ThemeTrait for Bulmix {
|
|||
HeadingDisplay::Subtitle => {
|
||||
h.alter_classes(ClassesOp::Replace(h.display().to_string()), "subtitle")
|
||||
}
|
||||
_ => h.alter_classes(ClassesOp::AddDefault, "title"),
|
||||
_ => h.alter_classes(ClassesOp::Add, "title"),
|
||||
};
|
||||
}
|
||||
COMPONENT_BASE_PARAGRAPH => {
|
||||
let p = component_as_mut::<Paragraph>(component);
|
||||
p.alter_classes(ClassesOp::AddDefault, "block");
|
||||
p.alter_classes(ClassesOp::Add, "block");
|
||||
match p.font_size() {
|
||||
FontSize::ExtraLarge => {
|
||||
p.alter_classes(ClassesOp::Replace(p.font_size().to_string()), "is-size-1");
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub struct Block {
|
|||
|
||||
impl ComponentTrait for Block {
|
||||
fn new() -> Self {
|
||||
Block::default().with_classes(ClassesOp::AddDefault, "block")
|
||||
Block::default().with_classes(ClassesOp::Add, "block")
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ pub struct Container {
|
|||
|
||||
impl ComponentTrait for Container {
|
||||
fn new() -> Self {
|
||||
Container::default()
|
||||
.with_classes(ClassesOp::AddDefault, flex::Direction::Default.to_string())
|
||||
Container::default().with_classes(ClassesOp::Add, flex::Direction::Default.to_string())
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ pub struct Item {
|
|||
impl ComponentTrait for Item {
|
||||
fn new() -> Self {
|
||||
Item::default()
|
||||
.with_item_classes(ClassesOp::AddDefault, "pt-flex__item")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "pt-flex__item-inner")
|
||||
.with_item_classes(ClassesOp::Add, "pt-flex__item")
|
||||
.with_inner_classes(ClassesOp::Add, "pt-flex__item-inner")
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub struct Button {
|
|||
|
||||
impl ComponentTrait for Button {
|
||||
fn new() -> Self {
|
||||
Button::default().with_classes(ClassesOp::AddDefault, "btn btn-primary form-button")
|
||||
Button::default().with_classes(ClassesOp::Add, "btn btn-primary form-button")
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub struct Date {
|
|||
|
||||
impl ComponentTrait for Date {
|
||||
fn new() -> Self {
|
||||
Date::default().with_classes(ClassesOp::AddDefault, "form-item form-type-date")
|
||||
Date::default().with_classes(ClassesOp::Add, "form-item form-type-date")
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub struct Form {
|
|||
impl ComponentTrait for Form {
|
||||
fn new() -> Self {
|
||||
Form::default()
|
||||
.with_classes(ClassesOp::AddDefault, "form")
|
||||
.with_classes(ClassesOp::Add, "form")
|
||||
.with_charset("UTF-8")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub struct Input {
|
|||
impl ComponentTrait for Input {
|
||||
fn new() -> Self {
|
||||
Input::default()
|
||||
.with_classes(ClassesOp::AddDefault, "form-item form-type-textfield")
|
||||
.with_classes(ClassesOp::Add, "form-item form-type-textfield")
|
||||
.with_size(Some(60))
|
||||
.with_maxlength(Some(128))
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ impl Input {
|
|||
if let Some(previous) = self.name.get() {
|
||||
self.alter_classes(ClassesOp::Remove, concat_string!("form-item-", previous));
|
||||
}
|
||||
self.alter_classes(ClassesOp::AddDefault, concat_string!("form-item-", name));
|
||||
self.alter_classes(ClassesOp::Add, concat_string!("form-item-", name));
|
||||
self.name.alter_value(name);
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pub struct Image {
|
|||
|
||||
impl ComponentTrait for Image {
|
||||
fn new() -> Self {
|
||||
Image::default().with_classes(ClassesOp::AddDefault, IMG_FLUID)
|
||||
Image::default().with_classes(ClassesOp::Add, IMG_FLUID)
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
@ -70,19 +70,19 @@ impl Image {
|
|||
pub fn with(source: &str) -> Self {
|
||||
Image::default()
|
||||
.with_source(source)
|
||||
.with_classes(ClassesOp::AddDefault, IMG_FLUID)
|
||||
.with_classes(ClassesOp::Add, IMG_FLUID)
|
||||
}
|
||||
|
||||
pub fn fixed(source: &str) -> Self {
|
||||
Image::default()
|
||||
.with_source(source)
|
||||
.with_classes(ClassesOp::AddDefault, IMG_FIXED)
|
||||
.with_classes(ClassesOp::Add, IMG_FIXED)
|
||||
}
|
||||
|
||||
pub fn pagetop() -> Self {
|
||||
Image::default()
|
||||
.with_source("/base/pagetop-logo.svg")
|
||||
.with_classes(ClassesOp::AddDefault, IMG_FIXED)
|
||||
.with_classes(ClassesOp::Add, IMG_FIXED)
|
||||
.with_size(ImageSize::Size(64, 64))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ pub struct Wrapper {
|
|||
impl ComponentTrait for Wrapper {
|
||||
fn new() -> Self {
|
||||
Wrapper::default()
|
||||
.with_classes(ClassesOp::AddDefault, "container")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "container")
|
||||
.with_classes(ClassesOp::Add, "container")
|
||||
.with_inner_classes(ClassesOp::Add, "container")
|
||||
}
|
||||
|
||||
fn handle(&self) -> Handle {
|
||||
|
|
@ -100,32 +100,32 @@ impl ComponentTrait for Wrapper {
|
|||
impl Wrapper {
|
||||
pub fn header() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::AddDefault, "header")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "container");
|
||||
.with_classes(ClassesOp::Add, "header")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Header;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn footer() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::AddDefault, "footer")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "container");
|
||||
.with_classes(ClassesOp::Add, "footer")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Footer;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn main() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::AddDefault, "main")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "container");
|
||||
.with_classes(ClassesOp::Add, "main")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Main;
|
||||
c
|
||||
}
|
||||
|
||||
pub fn section() -> Self {
|
||||
let mut c = Wrapper::default()
|
||||
.with_classes(ClassesOp::AddDefault, "section")
|
||||
.with_inner_classes(ClassesOp::AddDefault, "container");
|
||||
.with_classes(ClassesOp::Add, "section")
|
||||
.with_inner_classes(ClassesOp::Add, "container");
|
||||
c.wrapper_type = WrapperType::Section;
|
||||
c
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,33 +3,24 @@
|
|||
//! This *helper* differentiates between default classes (generally associated with styles provided
|
||||
//! by the theme) and user classes (for customizing components based on application styles).
|
||||
//!
|
||||
//! Default classes can be added using [AddDefault], while user classes can be added using [Add].
|
||||
//! Operations to [Remove], [Replace] or [ReplaceIfExists] a class, as well as to [Reset] user
|
||||
//! classes, are also provided.
|
||||
//! Classes can be added using [Add]. Operations to [Remove], [Replace] or [Toggle] a class, as well
|
||||
//! as [Clear] all classes, are also provided.
|
||||
//!
|
||||
//! Although the order of the classes is irrelevant (<https://stackoverflow.com/a/1321712>), default
|
||||
//! classes will be presented before user classes and duplicate classes will not be allowed.
|
||||
//! **OptionClasses** assumes that the order of the classes is irrelevant
|
||||
//! (<https://stackoverflow.com/a/1321712>), and duplicate classes will not be allowed.
|
||||
|
||||
use crate::fn_builder;
|
||||
|
||||
pub enum ClassesOp {
|
||||
AddDefault,
|
||||
Add,
|
||||
Remove,
|
||||
Replace(String),
|
||||
Toggle,
|
||||
Reset,
|
||||
Clear,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
enum ClassType {
|
||||
Default,
|
||||
User,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OptionClasses(Vec<(String, ClassType)>);
|
||||
pub struct OptionClasses(Vec<String>);
|
||||
|
||||
impl OptionClasses {
|
||||
pub fn new() -> Self {
|
||||
|
|
@ -50,52 +41,38 @@ impl OptionClasses {
|
|||
let classes: Vec<&str> = classes.split_ascii_whitespace().collect();
|
||||
|
||||
match op {
|
||||
ClassesOp::AddDefault => {
|
||||
let pos = match self.0.iter().position(|(_, t)| t.eq(&ClassType::User)) {
|
||||
Some(pos) => pos,
|
||||
None => self.0.len(),
|
||||
};
|
||||
self.add(&classes, pos, ClassType::Default);
|
||||
}
|
||||
ClassesOp::Add => {
|
||||
self.add(&classes, self.0.len(), ClassType::User);
|
||||
self.add(&classes, self.0.len());
|
||||
}
|
||||
ClassesOp::Remove => {
|
||||
for class in classes {
|
||||
self.0.retain(|(c, _)| c.ne(&class.to_string()));
|
||||
self.0.retain(|c| c.ne(&class.to_string()));
|
||||
}
|
||||
}
|
||||
ClassesOp::Replace(classes_to_replace) => {
|
||||
let mut pos = self.0.len();
|
||||
let mut class_type = ClassType::Default;
|
||||
let replace: Vec<&str> = classes_to_replace.split_ascii_whitespace().collect();
|
||||
for class in replace {
|
||||
if let Some(replace_pos) = self.0.iter().position(|(c, _)| c.eq(class)) {
|
||||
let (_, replace_type) = self.0.remove(replace_pos);
|
||||
if let Some(replace_pos) = self.0.iter().position(|c| c.eq(class)) {
|
||||
self.0.remove(replace_pos);
|
||||
if pos > replace_pos {
|
||||
pos = replace_pos;
|
||||
}
|
||||
if replace_type.eq(&ClassType::Default) {
|
||||
class_type = replace_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.add(&classes, pos, class_type);
|
||||
self.add(&classes, pos);
|
||||
}
|
||||
ClassesOp::Toggle => {
|
||||
for class in classes {
|
||||
if !class.is_empty() {
|
||||
if let Some(pos) = self.0.iter().position(|(c, _)| c.eq(class)) {
|
||||
if let Some(pos) = self.0.iter().position(|c| c.eq(class)) {
|
||||
self.0.remove(pos);
|
||||
} else {
|
||||
self.0.push((class.to_string(), ClassType::User));
|
||||
self.0.push(class.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClassesOp::Reset => {
|
||||
self.0.retain(|(_, t)| t.ne(&ClassType::User));
|
||||
}
|
||||
ClassesOp::Clear => {
|
||||
self.0.clear();
|
||||
}
|
||||
|
|
@ -104,10 +81,10 @@ impl OptionClasses {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn add(&mut self, classes: &Vec<&str>, mut pos: usize, class_type: ClassType) {
|
||||
fn add(&mut self, classes: &Vec<&str>, mut pos: usize) {
|
||||
for class in classes {
|
||||
if !class.is_empty() && !self.0.iter().any(|(c, _)| c.eq(class)) {
|
||||
self.0.insert(pos, (class.to_string(), class_type.clone()));
|
||||
if !class.is_empty() && !self.0.iter().any(|c| c.eq(class)) {
|
||||
self.0.insert(pos, class.to_string());
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -117,20 +94,14 @@ impl OptionClasses {
|
|||
|
||||
pub fn exists(&self, class: impl Into<String>) -> bool {
|
||||
let class: String = class.into();
|
||||
self.0.iter().any(|(c, _)| c.eq(&class))
|
||||
self.0.iter().any(|c| c.eq(&class))
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<String> {
|
||||
if self.0.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
self.0
|
||||
.iter()
|
||||
.map(|(c, _)| c.to_owned())
|
||||
.collect::<Vec<String>>()
|
||||
.join(" "),
|
||||
)
|
||||
Some(self.0.join(" "))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue