diff --git a/README.md b/README.md index 1ced135..51cf392 100644 --- a/README.md +++ b/README.md @@ -74,9 +74,9 @@ any of your responses. | `HX-Reswap` | `HxReswap` | `axum_htmx::responders::SwapOption` | | `HX-Retarget` | `HxRetarget` | `String` | | `HX-Reselect` | `HxReselect` | `String` | -| `HX-Trigger` | `HxResponseTrigger` | `axum_htmx::serde::HxEvent` | -| `HX-Trigger-After-Settle` | `HxResponseTriggerAfterSettle` | `axum_htmx::serde::HxEvent` | -| `HX-Trigger-After-Swap` | `HxResponseTriggerAfterSwap` | `axum_htmx::serde::HxEvent` | +| `HX-Trigger` | `HxResponseTrigger` | `axum_htmx::serde::HxEvent` | +| `HX-Trigger-After-Settle` | `HxResponseTrigger` | `axum_htmx::serde::HxEvent` | +| `HX-Trigger-After-Swap` | `HxResponseTrigger` | `axum_htmx::serde::HxEvent` | ## Request Guards diff --git a/src/responders/trigger.rs b/src/responders/trigger.rs index 82cb71f..343d216 100644 --- a/src/responders/trigger.rs +++ b/src/responders/trigger.rs @@ -91,24 +91,53 @@ fn events_to_header_value(events: Vec) -> Result for more information. #[derive(Debug, Clone)] -pub struct HxResponseTrigger(pub Vec); +pub struct HxResponseTrigger { + pub mode: TriggerMode, + pub events: Vec, +} -impl From for HxResponseTrigger -where - T: IntoIterator, - T::Item: Into, -{ - fn from(value: T) -> Self { - Self(value.into_iter().map(Into::into).collect()) +impl HxResponseTrigger { + /// Creates new [trigger](https://htmx.org/headers/hx-trigger/) with specified mode and events. + pub fn new>(mode: TriggerMode, events: impl IntoIterator) -> Self { + Self { + mode, + events: events.into_iter().map(Into::into).collect(), + } + } + + /// Creates new [normal](https://htmx.org/headers/hx-trigger/) trigger from events. + pub fn normal>(events: impl IntoIterator) -> Self { + Self::new(TriggerMode::Normal, events) + } + + /// Creates new [after settle](https://htmx.org/headers/hx-trigger/) trigger from events. + pub fn after_settle>(events: impl IntoIterator) -> Self { + Self::new(TriggerMode::AfterSettle, events) + } + + /// Creates new [after swap](https://htmx.org/headers/hx-trigger/) trigger from events. + pub fn after_swap>(events: impl IntoIterator) -> Self { + Self::new(TriggerMode::AfterSwap, events) } } @@ -116,77 +145,15 @@ impl IntoResponseParts for HxResponseTrigger { type Error = HxError; fn into_response_parts(self, mut res: ResponseParts) -> Result { - if !self.0.is_empty() { + if !self.events.is_empty() { + let header = match self.mode { + TriggerMode::Normal => headers::HX_TRIGGER, + TriggerMode::AfterSettle => headers::HX_TRIGGER_AFTER_SETTLE, + TriggerMode::AfterSwap => headers::HX_TRIGGER_AFTER_SETTLE, + }; + res.headers_mut() - .insert(headers::HX_TRIGGER, events_to_header_value(self.0)?); - } - - Ok(res) - } -} - -/// The `HX-Trigger-After-Settle` header. -/// -/// Allows you to trigger client-side events after the settle step. -/// -/// Will fail if the supplied events contain or produce characters that are not -/// visible ASCII (32-127) when serializing to JSON. -/// -/// See for more information. -#[derive(Debug, Clone)] -pub struct HxResponseTriggerAfterSettle(pub Vec); - -impl From for HxResponseTriggerAfterSettle -where - T: IntoIterator, - T::Item: Into, -{ - fn from(value: T) -> Self { - Self(value.into_iter().map(Into::into).collect()) - } -} - -impl IntoResponseParts for HxResponseTriggerAfterSettle { - type Error = HxError; - - fn into_response_parts(self, mut res: ResponseParts) -> Result { - if !self.0.is_empty() { - res.headers_mut() - .insert(headers::HX_TRIGGER, events_to_header_value(self.0)?); - } - - Ok(res) - } -} - -/// The `HX-Trigger-After-Swap` header. -/// -/// Allows you to trigger client-side events after the swap step. -/// -/// Will fail if the supplied events contain or produce characters that are not -/// visible ASCII (32-127) when serializing to JSON. -/// -/// See for more information. -#[derive(Debug, Clone)] -pub struct HxResponseTriggerAfterSwap(pub Vec); - -impl From for HxResponseTriggerAfterSwap -where - T: IntoIterator, - T::Item: Into, -{ - fn from(value: T) -> Self { - Self(value.into_iter().map(Into::into).collect()) - } -} - -impl IntoResponseParts for HxResponseTriggerAfterSwap { - type Error = HxError; - - fn into_response_parts(self, mut res: ResponseParts) -> Result { - if !self.0.is_empty() { - res.headers_mut() - .insert(headers::HX_TRIGGER, events_to_header_value(self.0)?); + .insert(header, events_to_header_value(self.events)?); } Ok(res) @@ -217,7 +184,8 @@ mod tests { assert_eq!(header_value, HeaderValue::from_static(expected_value)); - let value = events_to_header_value(HxResponseTrigger::from(["foo", "bar"]).0).unwrap(); + let value = + events_to_header_value(HxResponseTrigger::normal(["foo", "bar"]).events).unwrap(); assert_eq!(value, HeaderValue::from_static("foo, bar")); } }