fun_htmx/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3#![warn(missing_docs)]
4
5//! This crate provides a collection of [HTMX](https://htmx.org) attributes for [`fun-html`](https://github.com/jcornaz/fun-html/)
6//!
7//! # Example
8//!
9//! ```
10//! use fun_html::{elt::{script_empty, button, text}, attr::src};
11//! use fun_htmx::{hx_get, hx_swap_outer_html};
12//!
13//! let quick_start = [
14//!    script_empty([src("https://unpkg.com/htmx.org@2.0.3")]),
15//!    button(
16//!      [hx_get("/clicked"), hx_swap_outer_html()],
17//!      text("Click Me")
18//!    ),
19//! ];
20//! ```
21//! ## Feature flags
22//!
23//! * `std`: enabled by default. must be disabled to compile to `no_std`
24//! * `serde_json`: Add utilities like `hx_vals_serde(values: &impl Serialize)` that relies on `serde` serialization to output json
25//!
26
27extern crate alloc;
28
29use alloc::borrow::Cow;
30
31use fun_html::Attribute;
32
33/// [`hx-boost`](https://htmx.org/attributes/hx-boost/) attribute
34pub fn hx_boost(value: bool) -> Attribute {
35    Attribute::new("hx-boost", boolean(value))
36}
37
38/// [`hx-get`](https://htmx.org/attributes/hx-get/) attribute
39pub fn hx_get(path: impl Into<Cow<'static, str>>) -> Attribute {
40    Attribute::new("hx-get", path)
41}
42
43/// [`hx-post`](https://htmx.org/attributes/hx-post/) attribute
44pub fn hx_post(path: impl Into<Cow<'static, str>>) -> Attribute {
45    Attribute::new("hx-post", path)
46}
47
48/// [`hx-put`](https://htmx.org/attributes/hx-put/) attribute
49pub fn hx_put(path: impl Into<Cow<'static, str>>) -> Attribute {
50    Attribute::new("hx-put", path)
51}
52
53/// [`hx-patch`](https://htmx.org/attributes/hx-patch/) attribute
54pub fn hx_patch(path: impl Into<Cow<'static, str>>) -> Attribute {
55    Attribute::new("hx-patch", path)
56}
57
58/// [`hx-delete`](https://htmx.org/attributes/hx-delete/) attribute
59pub fn hx_delete(path: impl Into<Cow<'static, str>>) -> Attribute {
60    Attribute::new("hx-delete", path)
61}
62
63/// [`hx-trigger`](https://htmx.org/attributes/hx-trigger/) attribute
64pub fn hx_trigger(path: impl Into<Cow<'static, str>>) -> Attribute {
65    Attribute::new("hx-trigger", path)
66}
67
68/// [`hx-select`](https://htmx.org/attributes/hx-select/) attribute
69pub fn hx_select(path: impl Into<Cow<'static, str>>) -> Attribute {
70    Attribute::new("hx-select", path)
71}
72
73/// [`hx-target`](https://htmx.org/attributes/hx-target/) attribute
74pub fn hx_target(path: impl Into<Cow<'static, str>>) -> Attribute {
75    Attribute::new("hx-target", path)
76}
77
78/// [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
79pub fn hx_swap(path: impl Into<Cow<'static, str>>) -> Attribute {
80    Attribute::new("hx-swap", path)
81}
82
83/// `hx-swap="innerHTML"`
84///
85/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
86pub fn hx_swap_inner_html() -> Attribute {
87    hx_swap("innerHTML")
88}
89
90/// `hx-swap="outerHTML"`
91///
92/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
93pub fn hx_swap_outer_html() -> Attribute {
94    hx_swap("outerHTML")
95}
96
97/// `hx-swap="textContent"`
98///
99/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
100pub fn hx_swap_text_content() -> Attribute {
101    hx_swap("textContent")
102}
103
104/// `hx-swap="beforebegin"`
105///
106/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
107pub fn hx_swap_before_begin() -> Attribute {
108    hx_swap("beforebegin")
109}
110
111/// `hx-swap="afterbegin"`
112///
113/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
114pub fn hx_swap_after_begin() -> Attribute {
115    hx_swap("afterbegin")
116}
117
118/// `hx-swap="beforeend"`
119///
120/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
121pub fn hx_swap_before_end() -> Attribute {
122    hx_swap("beforeend")
123}
124
125/// `hx-swap="afterend"`
126///
127/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
128pub fn hx_swap_after_end() -> Attribute {
129    hx_swap("afterend")
130}
131
132/// `hx-swap="delete"`
133///
134/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
135pub fn hx_swap_delete() -> Attribute {
136    hx_swap("delete")
137}
138
139/// `hx-swap="none"`
140///
141/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
142pub fn hx_swap_none() -> Attribute {
143    hx_swap("none")
144}
145
146/// [`hx-push-url`](https://htmx.org/attributes/hx-push-url/) attribute using a boolean
147pub fn hx_push_url(value: bool) -> Attribute {
148    hx_push_url_str(boolean(value))
149}
150
151/// [`hx-push-url`](https://htmx.org/attributes/hx-push-url/) attribute using an URL
152pub fn hx_push_url_str(url: impl Into<Cow<'static, str>>) -> Attribute {
153    Attribute::new("hx-push-url", url)
154}
155
156/// [`hx-confirm`](https://htmx.org/attributes/hx-confirm/) attribute
157pub fn hx_confirm(value: impl Into<Cow<'static, str>>) -> Attribute {
158    Attribute::new("hx-confirm", value)
159}
160
161/// `hx-swap-oob="true"
162///
163/// See [`hx-swap`](https://htmx.org/attributes/hx-swap/) attribute
164pub fn hx_swap_oob() -> Attribute {
165    hx_swap_oob_swap("true")
166}
167
168/// [`hx-swap-oob`](https://htmx.org/attributes/hx-swap-oob/) attribute
169pub fn hx_swap_oob_swap(value: impl Into<Cow<'static, str>>) -> Attribute {
170    Attribute::new("hx-swap-oob", value)
171}
172
173/// [`hx-on*`](https://htmx.org/attributes/hx-on/) attributes
174pub fn hx_on(event: &'static str, action: impl Into<Cow<'static, str>>) -> Attribute {
175    Attribute::new_unsafe_name(alloc::format!("hx-on:{event}"), action)
176}
177
178/// [`hx-on:htmx:before-request`](https://htmx.org/attributes/hx-on/) attribute
179pub fn hx_on_htmx_before_request(action: impl Into<Cow<'static, str>>) -> Attribute {
180    Attribute::new("hx-on::before-request", action)
181}
182
183/// [`hx-on:htmx:after-request`](https://htmx.org/attributes/hx-on/) attribute
184pub fn hx_on_htmx_after_request(action: impl Into<Cow<'static, str>>) -> Attribute {
185    Attribute::new("hx-on::after-request", action)
186}
187
188/// [`hx-vals`](https://htmx.org/attributes/hx-vals/) attribute
189pub fn hx_vals(values: impl Into<Cow<'static, str>>) -> Attribute {
190    Attribute::new("hx-vals", values)
191}
192
193/// [`hx-disinherit`](https://htmx.org/attributes/hx-disinherit/) attribute
194pub fn hx_disinherit(attributes: impl IntoIterator<Item = &'static str>) -> Attribute {
195    let mut iter = attributes.into_iter();
196    let mut string = iter
197        .next()
198        .map(alloc::string::String::from)
199        .unwrap_or_default();
200    for value in iter {
201        string.push(' ');
202        string.push_str(value);
203    }
204    Attribute::new("hx-disinherit", string)
205}
206
207/// [`hx-disinherit="*"`](https://htmx.org/attributes/hx-disinherit/)
208pub fn hx_disinherit_all() -> Attribute {
209    Attribute::new("hx-disinherit", "*")
210}
211
212/// [`hx-vals`](https://htmx.org/attributes/hx-vals/) attribute using `serde` Serialization
213///
214/// The `values` must not fail to serialize.
215///
216/// # Panics
217///
218/// Panics if the serialization of `values` fail
219#[cfg(feature = "serde_json")]
220pub fn hx_vals_serde(values: &impl serde::Serialize) -> Attribute {
221    hx_vals(serde_json::to_string(values).expect("hx-vals values should not fail to serialize"))
222}
223
224fn boolean(value: bool) -> &'static str {
225    if value {
226        "true"
227    } else {
228        "false"
229    }
230}