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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! [`PatchElements`] patches HTML elements into the DOM.
use {
crate::{
DatastarEvent,
consts::{self, ElementPatchMode},
},
core::time::Duration,
};
/// [`PatchElements`] patches HTML elements into the DOM.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PatchElements {
/// `id` is can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// The HTML elements to patched into the DOM.
///
/// In case of [`ElementPatchMode::Remove`] this attribute will be `None`.
pub elements: Option<String>,
/// The CSS selector to use to patch the elements.
/// If not provided, Datastar will default to using the id attribute of the elements.
pub selector: Option<String>,
/// The mode to use when patching the element into the DOM.
/// If not provided the Datastar client side will default to [`ElementPatchMode::Outer`].
pub mode: ElementPatchMode,
/// Whether to use view transitions, if not provided the Datastar client side will default to `false`.
pub use_view_transition: bool,
}
impl PatchElements {
/// Creates a new [`PatchElements`] event with the given elements.
pub fn new(elements: impl Into<String>) -> Self {
Self {
id: None,
retry: Duration::from_millis(consts::DEFAULT_SSE_RETRY_DURATION),
elements: Some(elements.into()),
selector: None,
mode: ElementPatchMode::default(),
use_view_transition: consts::DEFAULT_ELEMENTS_USE_VIEW_TRANSITIONS,
}
}
/// Creates a new [`PatchElements`] to delete the elements for the given selector.
pub fn new_remove(selector: impl Into<String>) -> Self {
Self {
id: None,
retry: Duration::from_millis(consts::DEFAULT_SSE_RETRY_DURATION),
elements: None,
selector: Some(selector.into()),
mode: ElementPatchMode::Remove,
use_view_transition: consts::DEFAULT_ELEMENTS_USE_VIEW_TRANSITIONS,
}
}
/// Sets the `id` of the [`PatchElements`] event.
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
/// Sets the `retry` of the [`PatchElements`] event.
pub fn retry(mut self, retry: Duration) -> Self {
self.retry = retry;
self
}
/// Sets the `selector` of the [`PatchElements`] event.
pub fn selector(mut self, selector: impl Into<String>) -> Self {
self.selector = Some(selector.into());
self
}
/// Sets the `mode` of the [`PatchElements`] event.
pub fn mode(mut self, mode: ElementPatchMode) -> Self {
self.mode = mode;
self
}
/// Sets the `use_view_transition` of the [`PatchElements`] event.
pub fn use_view_transition(mut self, use_view_transition: bool) -> Self {
self.use_view_transition = use_view_transition;
self
}
/// Converts this [`PatchElements`] into a [`DatastarEvent`].
#[inline]
pub fn into_datastar_event(mut self) -> DatastarEvent {
let id = self.id.take();
self.convert_to_datastar_event_inner(id)
}
/// Copy this [`PatchElements`] as a [`DatastarEvent`].
#[inline]
pub fn as_datastar_event(&self) -> DatastarEvent {
self.convert_to_datastar_event_inner(self.id.clone())
}
fn convert_to_datastar_event_inner(&self, id: Option<String>) -> DatastarEvent {
let mut data: Vec<String> = Vec::new();
if let Some(selector) = &self.selector {
data.push(format!(
"{} {}",
consts::SELECTOR_DATALINE_LITERAL,
selector
));
}
if self.mode != ElementPatchMode::default() {
data.push(format!(
"{} {}",
consts::MODE_DATALINE_LITERAL,
self.mode.as_str()
));
}
if self.use_view_transition != consts::DEFAULT_ELEMENTS_USE_VIEW_TRANSITIONS {
data.push(format!(
"{} {}",
consts::USE_VIEW_TRANSITION_DATALINE_LITERAL,
self.use_view_transition
));
}
if let Some(ref elements) = self.elements {
for line in elements.lines() {
data.push(format!("{} {}", consts::ELEMENTS_DATALINE_LITERAL, line));
}
}
DatastarEvent {
event: consts::EventType::PatchElements,
id,
retry: self.retry,
data,
}
}
}
impl From<&PatchElements> for DatastarEvent {
#[inline]
fn from(val: &PatchElements) -> Self {
val.as_datastar_event()
}
}
impl From<PatchElements> for DatastarEvent {
#[inline]
fn from(val: PatchElements) -> Self {
val.into_datastar_event()
}
}