1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::future::Pending;
use async_ui_web_core::ContainerNodeFuture;
use async_ui_web_html::nodes::Text;
use js_sys::Array;
use wasm_bindgen::{JsValue, UnwrapThrowExt};
pub trait ShortcutRenderStr {
/// Render the [str] as an HTML text node with that content.
///
/// ```
/// # use async_ui_web::shortcut_traits::ShortcutRenderStr;
/// # let _ = async {
/// "hello world".render().await;
/// # };
/// ```
fn render(&self) -> ContainerNodeFuture<Pending<()>>;
}
impl ShortcutRenderStr for str {
fn render(&self) -> ContainerNodeFuture<Pending<()>> {
let t = Text::new();
t.set_data(self);
t.render()
}
}
pub trait ShortcutClassList {
/// Add a classname to this element, if not already present.
///
/// This method is equivalent to `elem.class_list().add_1(class_name).unwrap_throw()`.
fn add_class(&self, c: &str);
/// Add classnames to this element, ignoring those already present.
fn add_classes<'a>(&self, c: impl IntoIterator<Item = &'a str>);
/// Remove a classname from this element, if present.
///
/// This method is equivalent to `elem.class_list().remove_1(class_name).unwrap_throw()`.
fn del_class(&self, c: &str);
/// Remove classnames from this element, ignoring those not present.
fn del_classes<'a>(&self, c: impl IntoIterator<Item = &'a str>);
/// If the boolean `included` argument is true, add the classname to the element.
/// If the flag is false, remove the classname from the element.
///
/// This method is equivalent to `elem.class_list().toggle_with_force(c, included).unwrap_throw()`.
fn set_class(&self, c: &str, included: bool);
}
/// Convert an iterator of str to a JS array of strings.
fn strs_to_js_array<'a>(values: impl Iterator<Item = &'a str>) -> Array {
values.into_iter().map(JsValue::from_str).collect()
}
impl ShortcutClassList for web_sys::Element {
fn add_class(&self, c: &str) {
self.class_list().add_1(c).unwrap_throw();
}
fn add_classes<'a>(&self, c: impl IntoIterator<Item = &'a str>) {
self.class_list()
.add(&strs_to_js_array(c.into_iter()))
.unwrap_throw();
}
fn del_class(&self, c: &str) {
self.class_list().remove_1(c).unwrap();
}
fn del_classes<'a>(&self, c: impl IntoIterator<Item = &'a str>) {
self.class_list()
.remove(&strs_to_js_array(c.into_iter()))
.unwrap_throw();
}
fn set_class(&self, c: &str, included: bool) {
self.class_list()
.toggle_with_force(c, included)
.unwrap_throw();
}
}
pub trait ShortcutClassListBuilder: AsRef<web_sys::Element> {
/// Add a classname to the element and return reference to the input.
///
/// This is for writing the UI "declaratively".
/// ```
/// # let _ = async {
/// # use async_ui_web::{html::Div, prelude_traits::*};
/// # let children = std::future::pending::<()>();
/// Div::new().with_class("my-wrapper").render(children).await;
/// # };
/// ```
fn with_class(&self, c: &str) -> &Self {
self.as_ref().add_class(c);
self
}
/// Add classnames to the element and return reference to the input.
///
/// This is for writing the UI "declaratively".
/// ```
/// # let _ = async {
/// # use async_ui_web::{html::Div, prelude_traits::*};
/// # let children = std::future::pending::<()>();
/// Div::new().with_classes(["my-wrapper", "flex-vertical"]).render(children).await;
/// # };
/// ```
fn with_classes<'a>(&self, c: impl IntoIterator<Item = &'a str>) -> &Self {
self.as_ref().add_classes(c.into_iter());
self
}
}
impl<T: AsRef<web_sys::Element>> ShortcutClassListBuilder for T {}