use crate::element::{Component, Element};
use crate::style::{Color, Modifier, Style};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BadgeStyle {
#[default]
Simple,
Bracket,
Round,
Pill,
Filled,
}
#[derive(Debug, Clone)]
pub struct BadgeProps {
pub text: String,
pub color: Option<Color>,
pub bg_color: Option<Color>,
pub style: BadgeStyle,
pub bold: bool,
pub dim: bool,
}
impl Default for BadgeProps {
fn default() -> Self {
Self {
text: String::new(),
color: None,
bg_color: None,
style: BadgeStyle::Simple,
bold: false,
dim: false,
}
}
}
impl BadgeProps {
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
..Default::default()
}
}
#[must_use]
pub fn color(mut self, color: Color) -> Self {
self.color = Some(color);
self
}
#[must_use]
pub fn bg_color(mut self, color: Color) -> Self {
self.bg_color = Some(color);
self
}
#[must_use]
pub fn badge_style(mut self, style: BadgeStyle) -> Self {
self.style = style;
self
}
#[must_use]
pub fn bold(mut self) -> Self {
self.bold = true;
self
}
#[must_use]
pub fn dim(mut self) -> Self {
self.dim = true;
self
}
pub fn render_string(&self) -> String {
match self.style {
BadgeStyle::Simple => self.text.clone(),
BadgeStyle::Bracket => format!("[{}]", self.text),
BadgeStyle::Round => format!("({})", self.text),
BadgeStyle::Pill => format!("‹{}›", self.text),
BadgeStyle::Filled => format!(" {} ", self.text),
}
}
}
pub struct Badge;
impl Component for Badge {
type Props = BadgeProps;
fn render(props: &Self::Props) -> Element {
let content = props.render_string();
let mut style = Style::new();
if let Some(color) = props.color {
style = style.fg(color);
}
if let Some(bg) = props.bg_color {
style = style.bg(bg);
}
if props.bold {
style = style.add_modifier(Modifier::BOLD);
}
if props.dim {
style = style.add_modifier(Modifier::DIM);
}
Element::styled_text(&content, style)
}
}
pub fn badge(text: &str) -> String {
BadgeProps::new(text).render_string()
}
pub fn badge_bracket(text: &str) -> String {
BadgeProps::new(text)
.badge_style(BadgeStyle::Bracket)
.render_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_badge_simple() {
let props = BadgeProps::new("test");
assert_eq!(props.render_string(), "test");
}
#[test]
fn test_badge_bracket() {
let props = BadgeProps::new("INFO").badge_style(BadgeStyle::Bracket);
assert_eq!(props.render_string(), "[INFO]");
}
#[test]
fn test_badge_round() {
let props = BadgeProps::new("1").badge_style(BadgeStyle::Round);
assert_eq!(props.render_string(), "(1)");
}
#[test]
fn test_badge_pill() {
let props = BadgeProps::new("tag").badge_style(BadgeStyle::Pill);
assert_eq!(props.render_string(), "‹tag›");
}
#[test]
fn test_badge_filled() {
let props = BadgeProps::new("OK").badge_style(BadgeStyle::Filled);
assert_eq!(props.render_string(), " OK ");
}
#[test]
fn test_badge_helper() {
assert_eq!(badge("test"), "test");
assert_eq!(badge_bracket("test"), "[test]");
}
#[test]
fn test_badge_component_render() {
let props = BadgeProps::new("Test").color(Color::Green);
let elem = Badge::render(&props);
match elem {
Element::Text { content, style } => {
assert_eq!(content, "Test");
assert_eq!(style.fg, Color::Green);
}
_ => panic!("Expected Text element"),
}
}
}