diff --git a/Cargo.toml b/Cargo.toml index 72136b4..076c499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bootstrap-rs" -version = "0.2.6" +version = "0.2.7" authors = ["Thomas Gideon "] edition = "2018" diff --git a/src/alert/convert.rs b/src/alert/convert.rs deleted file mode 100644 index 0c7bdf7..0000000 --- a/src/alert/convert.rs +++ /dev/null @@ -1,17 +0,0 @@ -use super::Props; -use crate::prelude::*; - -impl<'a> From<&'a Props> for BootstrapProps<'a> { - fn from(props: &Props) -> BootstrapProps { - let class = &props.class; - let borders = collect_bs(&props.border, &props.borders); - let margins = collect_bs(&props.margin, &props.margins); - let paddings = collect_bs(&props.padding, &props.paddings); - BootstrapProps { - class, - borders, - margins, - paddings, - } - } -} diff --git a/src/alert/mod.rs b/src/alert/mod.rs index 588dbeb..cae4692 100644 --- a/src/alert/mod.rs +++ b/src/alert/mod.rs @@ -1,41 +1,14 @@ -mod convert; +mod props; -use crate::prelude::*; -use yew::{html::Children, prelude::*}; +use self::props::Props; +use crate::{prelude::*, render}; +use yew::prelude::*; pub struct Alert { link: ComponentLink, props: Props, } -#[derive(Properties, Default, Clone, PartialEq)] -pub struct Props { - pub on_close: Callback<()>, - pub color: Color, - #[prop_or_default] - pub aria_label: String, - #[prop_or_default] - pub role: String, - #[prop_or_default] - pub border: Option, - #[prop_or_default] - pub borders: Vec, - #[prop_or_default] - pub margin: Option, - #[prop_or_default] - pub margins: Vec, - #[prop_or_default] - pub padding: Option, - #[prop_or_default] - pub paddings: Vec, - #[prop_or_default] - pub class: String, - #[prop_or_default] - pub style: String, - #[prop_or_default] - pub children: Children, -} - impl Component for Alert { type Properties = Props; type Message = (); @@ -54,10 +27,8 @@ impl Component for Alert { } fn view(&self) -> Html { - let color_class = self.props.color.with_prefix("alert"); - let class = calculate_classes(format!("alert {}", color_class), (&self.props).into()); - html! { -
+ let html = html! { +
{ self.props.children.render() }
- } + }; + render::render_with_prefix( + &self.props, + vec!["alert", &self.props.color.with_prefix("alert")], + html, + ) } } diff --git a/src/alert/props.rs b/src/alert/props.rs new file mode 100644 index 0000000..1e2095f --- /dev/null +++ b/src/alert/props.rs @@ -0,0 +1,55 @@ +use crate::{prelude::*, props::*}; +use std::collections::HashMap; +use yew::prelude::*; + +#[derive(Properties, Default, Clone, PartialEq)] +pub struct Props { + // component specific + pub on_close: Callback<()>, + pub color: Color, + + // html specific + #[prop_or_default] + pub id: Option, + #[prop_or_default] + pub class: Classes, + #[prop_or_default] + pub style: String, + #[prop_or_default] + pub aria_label: Option, + #[prop_or_default] + pub role: Option, + #[prop_or_default] + pub children: Children, + + // bootstrap + #[prop_or_default] + pub border: Option, + #[prop_or_default] + pub borders: Vec, + #[prop_or_default] + pub margin: Option, + #[prop_or_default] + pub margins: Vec, + #[prop_or_default] + pub padding: Option, + #[prop_or_default] + pub paddings: Vec, +} + +impl<'a> From<&'a Props> for BootstrapProps<'a> { + fn from(props: &Props) -> BootstrapProps { + let class = &props.class; + let borders = collect_props(&props.border, &props.borders); + let margins = collect_props(&props.margin, &props.margins); + let paddings = collect_props(&props.padding, &props.paddings); + let attributes = HashMap::new(); + BootstrapProps { + class, + borders, + margins, + paddings, + attributes, + } + } +} diff --git a/src/breadcrumb/item.rs b/src/breadcrumb/item.rs index 8eedfed..3432cea 100644 --- a/src/breadcrumb/item.rs +++ b/src/breadcrumb/item.rs @@ -1,13 +1,17 @@ -use crate::prelude::*; +use crate::{prelude::*, props::*, render}; +use std::collections::HashMap; use yew::{html::Children, prelude::*}; pub struct BreadcrumbItem { props: Props, } -#[derive(Properties, Clone, PartialEq)] +#[derive(Properties, Clone, PartialEq, Default)] pub struct Props { + // component specific pub active: bool, + + // bootstrap specific #[prop_or_default] pub border: Option, #[prop_or_default] @@ -20,10 +24,14 @@ pub struct Props { pub padding: Option, #[prop_or_default] pub paddings: Vec, + + // html specific #[prop_or_default] - pub class: String, + pub id: Option, #[prop_or_default] - pub style: String, + pub class: Classes, + #[prop_or_default] + pub style: Option, #[prop_or_default] pub children: Children, } @@ -45,43 +53,87 @@ impl Component for BreadcrumbItem { } fn view(&self) -> Html { - if self.props.active { - html! { -
  • - { self.props.children.render() } -
  • - } + let (prefix, html) = if self.props.active { + ( + vec!["breadcrumb-item", "active"], + html! { +
  • + { self.props.children.render() } +
  • + }, + ) } else { - html! { -
  • - { self.props.children.render() } -
  • - } - } + ( + vec!["breadcrumb-item"], + html! { +
  • + { self.props.children.render() } +
  • + }, + ) + }; + render::render_with_prefix(&self.props, prefix, html) } } impl BreadcrumbItem { - fn classes(&self) -> String { + fn classes(&self) -> Classes { + let props: BootstrapProps<'_> = (&self.props).into(); + let mut classes = props.calculate_classes("breadcrumb-item"); if self.props.active { - calculate_classes("breadcrumb-item active", (&self.props).into()) - } else { - calculate_classes("breadcrumb-item", (&self.props).into()) + classes.push("active") } + classes } } impl<'a> From<&'a Props> for BootstrapProps<'a> { fn from(props: &Props) -> BootstrapProps { let class = &props.class; - let borders = collect_bs(&props.border, &props.borders); - let margins = collect_bs(&props.margin, &props.margins); - let paddings = collect_bs(&props.padding, &props.paddings); + let borders = collect_props(&props.border, &props.borders); + let margins = collect_props(&props.margin, &props.margins); + let paddings = collect_props(&props.padding, &props.paddings); + let mut attributes = HashMap::new(); + if let Some(ref id) = props.id { + attributes.insert("id", id); + } + if let Some(ref style) = props.style { + attributes.insert("style", style); + } BootstrapProps { class, borders, margins, paddings, + attributes, } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_active_prop() { + let item = BreadcrumbItem { + props: Props { + active: true, + id: Some("test".into()), + margin: Some(Margin(Edge::All, 3)), + padding: Some(Padding(Edge::Top, 3)), + ..Props::default() + }, + }; + let expected = html! { + + }; + assert_eq!(expected, item.view()); + } +} diff --git a/src/breadcrumb/mod.rs b/src/breadcrumb/mod.rs index bfe8aee..5866e59 100644 --- a/src/breadcrumb/mod.rs +++ b/src/breadcrumb/mod.rs @@ -1,6 +1,6 @@ mod item; -use crate::prelude::*; +use crate::{prelude::*, props::*, render}; pub use item::BreadcrumbItem; use yew::prelude::*; @@ -25,19 +25,13 @@ impl Component for Breadcrumb { } fn view(&self) -> Html { - let class = calculate_classes("breadcrumb", (&self.props).into()); - html! { -