#![warn(
clippy::all,
clippy::missing_errors_doc,
clippy::style,
clippy::unseparated_literal_suffix,
clippy::pedantic,
clippy::nursery
)]
use serde::Serialize;
use wasm_bindgen::prelude::*;
#[derive(Debug, Clone, Serialize, Copy, Default)]
#[serde(rename_all = "lowercase")]
pub enum Gravity {
#[default]
Top,
Bottom,
}
impl AsRef<str> for Gravity {
fn as_ref(&self) -> &str {
match self {
Self::Top => "top",
Self::Bottom => "bottom",
}
}
}
#[derive(Debug, Clone, Serialize, Copy, Default)]
#[serde(rename_all = "lowercase")]
pub enum Position {
Left,
#[default]
Right,
Center,
}
impl AsRef<str> for Position {
fn as_ref(&self) -> &str {
match self {
Self::Left => "left",
Self::Right => "right",
Self::Center => "center",
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct ToastifyOptions {
pub text: String,
pub duration: u32,
pub destination: Option<String>,
pub close: bool,
pub gravity: Gravity,
pub position: Position,
#[serde(rename = "newWindow")]
pub new_window: bool,
#[serde(rename = "stopOnFocus")]
pub stop_on_focus: bool,
#[serde(rename = "className")]
#[serde(skip_serializing_if = "Option::is_none")]
pub class_name: Option<String>,
#[serde(with = "serde_wasm_bindgen::preserve")]
pub style: js_sys::Object,
#[serde(with = "serde_wasm_bindgen::preserve")]
#[serde(rename = "onClick")]
pub on_click: JsValue,
}
impl Default for ToastifyOptions {
fn default() -> Self {
Self {
text: String::new(),
duration: 3000,
destination: None,
close: true,
gravity: Gravity::Top,
position: Position::Right,
new_window: false,
stop_on_focus: true,
class_name: None,
style: js_sys::Object::new(),
on_click: JsValue::NULL,
}
}
}
impl ToastifyOptions {
pub fn add_style(self, style_property: &str, value: &str) -> Result<Self, JsValue> {
js_sys::Reflect::set(
&self.style,
&JsValue::from_str(style_property),
&JsValue::from_str(value),
)?;
Ok(self)
}
#[must_use]
pub fn add_on_click<T>(self, callback: T) -> Self
where
T: Fn(),
{
let callback = Closure::wrap(Box::new(callback) as Box<dyn Fn()>);
let mut this = self;
this.on_click = callback.into_js_value();
this
}
pub fn show(self) {
let options: JsValue = self.into();
toasts(&options).show_toast();
}
}
impl From<ToastifyOptions> for JsValue {
fn from(val: ToastifyOptions) -> Self {
serde_wasm_bindgen::to_value(&val).expect("Failed to serialize Toast")
}
}
#[wasm_bindgen]
extern "C" {
#[derive(Debug, Clone)]
pub type Toastify;
#[wasm_bindgen(js_namespace = window, js_name = Toastify)]
pub fn toasts(options: &JsValue) -> Toastify;
#[wasm_bindgen(method, js_name = showToast)]
pub fn show_toast(this: &Toastify);
}