use crate::components::{Box as RnkBox, Text};
use crate::core::{BorderStyle, Color, Element, FlexDirection};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AlertLevel {
#[default]
Info,
Success,
Warning,
Error,
}
#[derive(Debug, Clone)]
pub struct Alert {
message: String,
level: AlertLevel,
title: Option<String>,
dismissible: bool,
}
impl Alert {
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
level: AlertLevel::Info,
title: None,
dismissible: false,
}
}
pub fn info(message: impl Into<String>) -> Self {
Self::new(message).level(AlertLevel::Info)
}
pub fn success(message: impl Into<String>) -> Self {
Self::new(message).level(AlertLevel::Success)
}
pub fn warning(message: impl Into<String>) -> Self {
Self::new(message).level(AlertLevel::Warning)
}
pub fn error(message: impl Into<String>) -> Self {
Self::new(message).level(AlertLevel::Error)
}
pub fn level(mut self, level: AlertLevel) -> Self {
self.level = level;
self
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn dismissible(mut self) -> Self {
self.dismissible = true;
self
}
pub fn into_element(self) -> Element {
let (icon, color, bg) = match self.level {
AlertLevel::Info => ("ℹ", Color::Cyan, Color::Ansi256(23)),
AlertLevel::Success => ("✓", Color::Green, Color::Ansi256(22)),
AlertLevel::Warning => ("âš ", Color::Yellow, Color::Ansi256(58)),
AlertLevel::Error => ("✗", Color::Red, Color::Ansi256(52)),
};
let mut children = Vec::new();
let mut header_children = vec![
Text::new(format!("{} ", icon))
.color(color)
.bold()
.into_element(),
];
if let Some(title) = &self.title {
header_children.push(
Text::new(title)
.color(color)
.bold()
.into_element(),
);
} else {
header_children.push(
Text::new(&self.message)
.color(Color::White)
.into_element(),
);
}
if self.dismissible {
header_children.push(
Text::new(" [x]")
.color(Color::BrightBlack)
.into_element(),
);
}
children.push(
RnkBox::new()
.flex_direction(FlexDirection::Row)
.children(header_children)
.into_element(),
);
if self.title.is_some() {
children.push(
Text::new(format!(" {}", self.message))
.color(Color::White)
.into_element(),
);
}
RnkBox::new()
.flex_direction(FlexDirection::Column)
.padding_x(1.0)
.padding_y(0.5)
.background(bg)
.border_style(BorderStyle::Round)
.border_color(color)
.children(children)
.into_element()
}
}
impl Default for Alert {
fn default() -> Self {
Self::new("")
}
}
pub fn alert_info(message: impl Into<String>) -> Element {
Alert::info(message).into_element()
}
pub fn alert_success(message: impl Into<String>) -> Element {
Alert::success(message).into_element()
}
pub fn alert_warning(message: impl Into<String>) -> Element {
Alert::warning(message).into_element()
}
pub fn alert_error(message: impl Into<String>) -> Element {
Alert::error(message).into_element()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_alert_creation() {
let a = Alert::new("Test message");
assert_eq!(a.message, "Test message");
}
#[test]
fn test_alert_levels() {
let _ = Alert::info("Info").into_element();
let _ = Alert::success("Success").into_element();
let _ = Alert::warning("Warning").into_element();
let _ = Alert::error("Error").into_element();
}
#[test]
fn test_alert_with_title() {
let a = Alert::error("Details").title("Error!");
assert_eq!(a.title, Some("Error!".to_string()));
}
#[test]
fn test_alert_helpers() {
let _ = alert_info("Info");
let _ = alert_success("Success");
let _ = alert_warning("Warning");
let _ = alert_error("Error");
}
}