use std::ops::{Deref, DerefMut};
use blinc_layout::div::{Div, ElementBuilder, ElementTypeId};
use blinc_layout::prelude::*;
use blinc_theme::ThemeState;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum AlertVariant {
#[default]
Default,
Success,
Warning,
Destructive,
}
pub struct Alert {
inner: Div,
message: String,
variant: AlertVariant,
}
impl Alert {
pub fn new(message: impl Into<String>) -> Self {
Self::with_variant(message, AlertVariant::default())
}
fn with_variant(message: impl Into<String>, variant: AlertVariant) -> Self {
let message = message.into();
let inner = Self::build_div(&message, variant);
Self {
inner,
message,
variant,
}
}
fn build_div(message: &str, variant: AlertVariant) -> Div {
let variant_class = match variant {
AlertVariant::Default => "cn-alert--info",
AlertVariant::Success => "cn-alert--success",
AlertVariant::Warning => "cn-alert--warning",
AlertVariant::Destructive => "cn-alert--error",
};
div()
.class("cn-alert")
.class(variant_class)
.child(text(message).size(14.0))
}
pub fn variant(mut self, variant: AlertVariant) -> Self {
self.variant = variant;
self.inner = Self::build_div(&self.message, variant);
self
}
pub fn class(mut self, name: impl Into<String>) -> Self {
self.inner = self.inner.class(name);
self
}
pub fn id(mut self, id: &str) -> Self {
self.inner = self.inner.id(id);
self
}
}
impl Deref for Alert {
type Target = Div;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for Alert {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl ElementBuilder for Alert {
fn build(&self, tree: &mut blinc_layout::tree::LayoutTree) -> blinc_layout::tree::LayoutNodeId {
self.inner.build(tree)
}
fn render_props(&self) -> blinc_layout::element::RenderProps {
self.inner.render_props()
}
fn children_builders(&self) -> &[Box<dyn ElementBuilder>] {
self.inner.children_builders()
}
fn event_handlers(&self) -> Option<&blinc_layout::event_handler::EventHandlers> {
ElementBuilder::event_handlers(&self.inner)
}
fn layout_style(&self) -> Option<&taffy::Style> {
ElementBuilder::layout_style(&self.inner)
}
fn element_type_id(&self) -> ElementTypeId {
ElementBuilder::element_type_id(&self.inner)
}
fn element_classes(&self) -> &[String] {
self.inner.element_classes()
}
}
pub fn alert(message: impl Into<String>) -> Alert {
Alert::new(message)
}
pub struct AlertBox {
inner: Div,
variant: AlertVariant,
}
impl AlertBox {
pub fn new() -> Self {
Self {
inner: Self::build_container(AlertVariant::default()),
variant: AlertVariant::default(),
}
}
fn build_container(variant: AlertVariant) -> Div {
let variant_class = match variant {
AlertVariant::Default => "cn-alert--info",
AlertVariant::Success => "cn-alert--success",
AlertVariant::Warning => "cn-alert--warning",
AlertVariant::Destructive => "cn-alert--error",
};
div().class("cn-alert-box").class(variant_class).flex_col()
}
pub fn variant(mut self, variant: AlertVariant) -> Self {
self.variant = variant;
self.inner = Self::build_container(variant);
self
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.inner = self.inner.child(text(title).size(14.0).semibold());
self
}
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.inner = self.inner.child(text(desc).size(14.0));
self
}
pub fn class(mut self, name: impl Into<String>) -> Self {
self.inner = self.inner.class(name);
self
}
pub fn id(mut self, id: &str) -> Self {
self.inner = self.inner.id(id);
self
}
}
impl Default for AlertBox {
fn default() -> Self {
Self::new()
}
}
impl Deref for AlertBox {
type Target = Div;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for AlertBox {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl ElementBuilder for AlertBox {
fn build(&self, tree: &mut blinc_layout::tree::LayoutTree) -> blinc_layout::tree::LayoutNodeId {
self.inner.build(tree)
}
fn render_props(&self) -> blinc_layout::element::RenderProps {
self.inner.render_props()
}
fn children_builders(&self) -> &[Box<dyn ElementBuilder>] {
self.inner.children_builders()
}
fn event_handlers(&self) -> Option<&blinc_layout::event_handler::EventHandlers> {
ElementBuilder::event_handlers(&self.inner)
}
fn layout_style(&self) -> Option<&taffy::Style> {
ElementBuilder::layout_style(&self.inner)
}
fn element_type_id(&self) -> ElementTypeId {
ElementBuilder::element_type_id(&self.inner)
}
fn element_classes(&self) -> &[String] {
self.inner.element_classes()
}
}
pub fn alert_box() -> AlertBox {
AlertBox::new()
}
#[cfg(test)]
mod tests {
use super::*;
fn init_theme() {
let _ = ThemeState::try_get().unwrap_or_else(|| {
ThemeState::init_default();
ThemeState::get()
});
}
#[test]
fn test_alert_default() {
init_theme();
let _ = alert("Test message");
}
#[test]
fn test_alert_variants() {
init_theme();
let _ = alert("Info").variant(AlertVariant::Default);
let _ = alert("Success").variant(AlertVariant::Success);
let _ = alert("Warning").variant(AlertVariant::Warning);
let _ = alert("Error").variant(AlertVariant::Destructive);
}
#[test]
fn test_alert_box() {
init_theme();
let _ = alert_box()
.variant(AlertVariant::Warning)
.title("Warning")
.description("This is a warning message");
}
}