use std::borrow::Cow;
use crate::Classes;
use crate::class_name::ClassName;
use crate::condition::ClassCondition;
impl From<&'static str> for Classes {
fn from(name: &'static str) -> Self {
Classes::new().add(name)
}
}
impl From<String> for Classes {
fn from(name: String) -> Self {
Classes::new().add(name)
}
}
impl From<Cow<'static, str>> for Classes {
fn from(name: Cow<'static, str>) -> Self {
Classes::new().add(name)
}
}
impl From<ClassName> for Classes {
fn from(name: ClassName) -> Self {
Classes::new().add(name)
}
}
impl<N: Clone + Into<ClassName>> From<&[N]> for Classes {
fn from(names: &[N]) -> Self {
Classes::new().add_all(names.iter().cloned())
}
}
impl<N: Into<ClassName>, const M: usize> From<[N; M]> for Classes {
fn from(names: [N; M]) -> Self {
Classes::new().add_all(names)
}
}
impl<N: Into<ClassName>, C: Into<ClassCondition>> From<(N, C)> for Classes {
fn from((name, when): (N, C)) -> Self {
Classes::new().add_reactive(name, when)
}
}
impl<N: Clone + Into<ClassName>, C: Clone + Into<ClassCondition>> From<&[(N, C)]> for Classes {
fn from(entries: &[(N, C)]) -> Self {
let mut classes = Classes::new();
for (name, when) in entries.iter().cloned() {
classes = classes.add_reactive(name, when);
}
classes
}
}
impl<N: Into<ClassName>, C: Into<ClassCondition>, const M: usize> From<[(N, C); M]> for Classes {
fn from(entries: [(N, C); M]) -> Self {
let mut classes = Classes::new();
for (name, when) in entries {
classes = classes.add_reactive(name, when);
}
classes
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use assertr::prelude::*;
use leptos::prelude::{Get, Memo, ReadSignal, RwSignal, Set, signal};
use crate::{ClassName, Classes};
mod from_unconditional {
use super::*;
#[test]
fn static_str_renders_token() {
let classes: Classes = "foo".into();
assert_that!(classes.to_class_string()).is_equal_to("foo".to_string());
}
#[test]
fn string_renders_token() {
let classes: Classes = String::from("foo").into();
assert_that!(classes.to_class_string()).is_equal_to("foo".to_string());
}
#[test]
fn cow_borrowed_renders_token() {
let classes: Classes = Cow::Borrowed("foo").into();
assert_that!(classes.to_class_string()).is_equal_to("foo".to_string());
}
#[test]
fn cow_owned_renders_token() {
let cow: Cow<'static, str> = Cow::Owned(String::from("foo"));
let classes: Classes = cow.into();
assert_that!(classes.to_class_string()).is_equal_to("foo".to_string());
}
#[test]
fn class_name_renders_token() {
let name = ClassName::try_new("foo").unwrap();
let classes: Classes = name.into();
assert_that!(classes.to_class_string()).is_equal_to("foo".to_string());
}
#[test]
fn slice_of_static_str_renders_all_tokens_in_order() {
let names: &[&'static str] = &["foo", "bar", "baz"];
let classes: Classes = names.into();
assert_that!(classes.to_class_string()).is_equal_to("foo bar baz".to_string());
}
#[test]
fn slice_of_string_renders_all_tokens_in_order() {
let names: &[String] = &[String::from("foo"), String::from("bar")];
let classes: Classes = names.into();
assert_that!(classes.to_class_string()).is_equal_to("foo bar".to_string());
}
#[test]
fn array_of_static_str_renders_all_tokens_in_order() {
let classes = Classes::from(["foo", "bar", "baz"]);
assert_that!(classes.to_class_string()).is_equal_to("foo bar baz".to_string());
}
#[test]
fn array_of_string_renders_all_tokens_in_order() {
let classes = Classes::from([String::from("foo"), String::from("bar")]);
assert_that!(classes.to_class_string()).is_equal_to("foo bar".to_string());
}
#[test]
fn slice_of_class_name_renders_all_tokens_in_order() {
let names: &[ClassName] = &[
ClassName::try_new("foo").unwrap(),
ClassName::try_new("bar").unwrap(),
];
let classes: Classes = names.into();
assert_that!(classes.to_class_string()).is_equal_to("foo bar".to_string());
}
#[test]
fn array_of_class_name_renders_all_tokens_in_order() {
let classes = Classes::from([
ClassName::try_new("foo").unwrap(),
ClassName::try_new("bar").unwrap(),
]);
assert_that!(classes.to_class_string()).is_equal_to("foo bar".to_string());
}
#[test]
fn empty_slice_yields_empty_classes() {
let names: &[&'static str] = &[];
let classes: Classes = names.into();
assert_that!(classes.to_class_string()).is_equal_to(String::new());
}
#[test]
fn empty_array_yields_empty_classes() {
let names: [&'static str; 0] = [];
let classes = Classes::from(names);
assert_that!(classes.to_class_string()).is_equal_to(String::new());
}
}
mod from_conditional {
use super::*;
#[test]
fn read_signal_renders_initial_active_token() {
let (is_active, _) = signal(true);
let classes = Classes::from(("active", is_active));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
#[test]
fn rw_signal_renders_initial_active_token() {
let is_active = RwSignal::new(true);
let classes = Classes::from(("active", is_active));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
#[test]
fn memo_renders_initial_active_token() {
let backing = RwSignal::new(true);
let memo = Memo::new(move |_| backing.get());
let classes = Classes::from(("active", memo));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
#[test]
fn closure_renders_initial_active_token() {
let (is_active, _) = signal(true);
let classes = Classes::from(("active", move || is_active.get()));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
#[test]
fn string_name_with_signal_renders() {
let (is_active, _) = signal(true);
let classes = Classes::from((String::from("active"), is_active));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
#[test]
fn array_of_tuples_renders_active_entries_only() {
let (is_first, _) = signal(true);
let (is_second, _) = signal(false);
let classes = Classes::from([("first", is_first), ("second", is_second)]);
assert_that!(classes.to_class_string()).is_equal_to("first".to_string());
}
#[test]
fn slice_of_tuples_renders_active_entries_only() {
let (is_first, _) = signal(true);
let (is_second, _) = signal(false);
let entries: &[(&'static str, ReadSignal<bool>)] =
&[("first", is_first), ("second", is_second)];
let classes: Classes = entries.into();
assert_that!(classes.to_class_string()).is_equal_to("first".to_string());
}
#[test]
fn signal_mutation_propagates_to_render() {
let (is_active, set_is_active) = signal(true);
let classes = Classes::from(("active", is_active));
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
set_is_active.set(false);
assert_that!(classes.to_class_string()).is_equal_to(String::new());
set_is_active.set(true);
assert_that!(classes.to_class_string()).is_equal_to("active".to_string());
}
}
}