diff --git a/src/Htmxor/HtmxConfig.cs b/src/Htmxor/HtmxConfig.cs
index c677138..9c4763d 100644
--- a/src/Htmxor/HtmxConfig.cs
+++ b/src/Htmxor/HtmxConfig.cs
@@ -8,6 +8,8 @@ namespace Htmxor;
///
public partial record class HtmxConfig
{
+ private SwapStyle? defaultSwapStyle;
+
///
/// Defaults to if this property is null. really only useful for testing
///
@@ -31,7 +33,11 @@ public partial record class HtmxConfig
/// Defaults to if this property is null.
///
[JsonPropertyName("defaultSwapStyle")]
- public SwapStyle? DefaultSwapStyle { get; set; }
+ public SwapStyle? DefaultSwapStyle
+ {
+ get => defaultSwapStyle;
+ set => defaultSwapStyle = value is SwapStyle.Default ? null : value;
+ }
///
/// Defaults to if this property is null.
diff --git a/src/Htmxor/Http/HtmxResponse.cs b/src/Htmxor/Http/HtmxResponse.cs
index 74d06ee..e47c4c4 100644
--- a/src/Htmxor/Http/HtmxResponse.cs
+++ b/src/Htmxor/Http/HtmxResponse.cs
@@ -144,8 +144,8 @@ public HtmxResponse ReplaceUrl(string url)
/// This object instance.
public HtmxResponse Reswap(string modifier)
{
+ ArgumentNullException.ThrowIfNullOrWhiteSpace(modifier);
headers[HtmxResponseHeaderNames.Reswap] = modifier;
-
return this;
}
@@ -159,20 +159,16 @@ public HtmxResponse Reswap(SwapStyle swapStyle, string? modifier = null)
{
AssertIsHtmxRequest();
- var style = swapStyle switch
+ if (swapStyle is SwapStyle.Default)
{
- SwapStyle.InnerHTML => "innerHTML",
- SwapStyle.OuterHTML => "outerHTML",
- SwapStyle.BeforeBegin => "beforebegin",
- SwapStyle.AfterBegin => "afterbegin",
- SwapStyle.BeforeEnd => "beforeend",
- SwapStyle.AfterEnd => "afterend",
- SwapStyle.Delete => "delete",
- SwapStyle.None => "none",
- _ => throw new SwitchExpressionException(swapStyle),
- };
+ Reswap(modifier);
+ return this;
+ }
- var value = modifier != null ? $"{style} {modifier}" : style;
+ var style = swapStyle.ToHtmxString();
+ var value = !string.IsNullOrWhiteSpace(modifier)
+ ? $"{style} {modifier}"
+ : style;
headers[HtmxResponseHeaderNames.Reswap] = value;
@@ -180,16 +176,18 @@ public HtmxResponse Reswap(SwapStyle swapStyle, string? modifier = null)
}
///
- /// Allows you to specify how the response will be swapped.
+ /// Allows you to specify how the response will be swapped.
///
///
///
- ///
+ /// This object instance.
public HtmxResponse Reswap(SwapStyleBuilder swapStyle)
{
- var (style, modifier) = swapStyle.Build();
+ var (style, modifier) = swapStyle.Build();
- return style is null ? Reswap(modifier) : Reswap((SwapStyle)style, modifier);
+ return style is SwapStyle.Default
+ ? Reswap(modifier)
+ : Reswap(style, modifier);
}
///
@@ -224,11 +222,12 @@ public HtmxResponse Reselect(string selector)
/// Sets response code to stop polling
///
///
+ /// This object instance.
public HtmxResponse StopPolling()
{
- context.Response.StatusCode = HtmxStatusCodes.StopPolling;
+ context.Response.StatusCode = HtmxStatusCodes.StopPolling;
- return this;
+ return this;
}
///
@@ -314,7 +313,7 @@ public override string ToString()
private void AssertIsHtmxRequest()
{
- if(!isHtmxRequest)
+ if (!isHtmxRequest)
{
throw new InvalidOperationException(
"The active request is not an htmx request. " +
diff --git a/src/Htmxor/Http/SwapStyleBuilder.cs b/src/Htmxor/Http/SwapStyleBuilder.cs
index 433eb40..0b4afc3 100644
--- a/src/Htmxor/Http/SwapStyleBuilder.cs
+++ b/src/Htmxor/Http/SwapStyleBuilder.cs
@@ -1,5 +1,6 @@
using System.Collections;
using System.Collections.Specialized;
+using System.Diagnostics;
using System.Numerics;
namespace Htmxor.Http;
@@ -7,16 +8,17 @@ namespace Htmxor.Http;
///
/// A builder class for constructing a swap style command string for HTMX responses.
///
-public sealed class SwapStyleBuilder
+[DebuggerDisplay("{ToString(),nq}")]
+public sealed class SwapStyleBuilder
{
- private readonly SwapStyle? style;
- private readonly OrderedDictionary modifiers = new();
+ private readonly SwapStyle style;
+ private readonly OrderedDictionary modifiers = new(StringComparer.Ordinal);
///
/// Initializes a new instance of the SwapStyleBuilder with a specified swap style.
///
/// The initial swap style to be applied.
- public SwapStyleBuilder(SwapStyle? style = null)
+ public SwapStyleBuilder(SwapStyle style = SwapStyle.Default)
{
this.style = style;
}
@@ -32,6 +34,7 @@ public SwapStyleBuilder(SwapStyle? style = null)
///
/// The amount of time htmx should wait after receiving a
/// response to swap the content.
+ /// This object instance.
public SwapStyleBuilder AfterSwapDelay(TimeSpan time)
{
AddModifier("swap", time.TotalMilliseconds < 1000 ? $"{time.TotalMilliseconds}ms" : $"{time.TotalSeconds}s");
@@ -50,11 +53,12 @@ public SwapStyleBuilder AfterSwapDelay(TimeSpan time)
///
/// The amount of time htmx should wait after receiving a
/// response to swap the content.
+ /// This object instance.
public SwapStyleBuilder AfterSettleDelay(TimeSpan time)
{
- AddModifier("settle", time.TotalMilliseconds < 1000 ? $"{time.TotalMilliseconds}ms" : $"{time.TotalSeconds}s");
+ AddModifier("settle", time.TotalMilliseconds < 1000 ? $"{time.TotalMilliseconds}ms" : $"{time.TotalSeconds}s");
- return this;
+ return this;
}
///
@@ -67,7 +71,7 @@ public SwapStyleBuilder AfterSettleDelay(TimeSpan time)
///
/// The scroll direction after the swap.
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder Scroll(ScrollDirection direction, string? selector = null)
{
switch (direction)
@@ -92,7 +96,7 @@ public SwapStyleBuilder Scroll(ScrollDirection direction, string? selector = nul
/// is present then the page is scrolled to the top of the content identified by the css selector.
///
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ScrollTop(string? selector = null) => Scroll(ScrollDirection.Top, selector);
///
@@ -104,9 +108,9 @@ public SwapStyleBuilder Scroll(ScrollDirection direction, string? selector = nul
/// is present then the page is scrolled to the bottom of the content identified by the css selector.
///
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ScrollBottom(string? selector = null) => Scroll(ScrollDirection.Bottom, selector);
-
+
///
/// Determines whether to ignore the document title in the swap response by appending the modifier
/// ignoreTitle:.
@@ -117,7 +121,7 @@ public SwapStyleBuilder Scroll(ScrollDirection direction, string? selector = nul
/// This keeps the current title unchanged regardless of the incoming swap content's title tag.
///
/// Whether to ignore the title.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder IgnoreTitle(bool ignore = true)
{
AddModifier("ignoreTitle", ignore);
@@ -132,7 +136,7 @@ public SwapStyleBuilder IgnoreTitle(bool ignore = true)
/// This method ensures the title of the document is updated according to the swap response by removing any
/// ignoreTitle modifiers, effectively setting ignoreTitle:false.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder IncludeTitle() => IgnoreTitle(false);
///
@@ -143,7 +147,7 @@ public SwapStyleBuilder IgnoreTitle(bool ignore = true)
/// will add the modifier transition:true to enable smooth transitions.
///
/// Whether to show transition effects.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder Transition(bool show)
{
AddModifier("transition", show);
@@ -157,7 +161,7 @@ public SwapStyleBuilder Transition(bool show)
///
/// By calling this method, transition effects are enabled for the swap, adding the modifier transition:true.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder IncludeTransition() => Transition(true);
///
@@ -166,7 +170,7 @@ public SwapStyleBuilder Transition(bool show)
///
/// This method disables transition effects by adding the modifier transition:false to the swap commands.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder IgnoreTransition() => Transition(false);
///
@@ -180,7 +184,7 @@ public SwapStyleBuilder Transition(bool show)
/// will be focus-scroll:false
///
/// Whether to scroll to the focus element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ScrollFocus(bool scroll = true)
{
AddModifier("focus-scroll", scroll);
@@ -195,7 +199,7 @@ public SwapStyleBuilder ScrollFocus(bool scroll = true)
///
/// Adds a modifier of focus-scroll:false
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder PreserveFocus() => ScrollFocus(false);
///
@@ -209,7 +213,7 @@ public SwapStyleBuilder ScrollFocus(bool scroll = true)
///
/// The scroll direction after swap.
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowOn(ScrollDirection direction, string? selector = null)
{
switch (direction)
@@ -233,7 +237,7 @@ public SwapStyleBuilder ShowOn(ScrollDirection direction, string? selector = nul
/// .
///
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowOnTop(string? selector = null) => ShowOn(ScrollDirection.Top, selector);
///
@@ -244,18 +248,18 @@ public SwapStyleBuilder ShowOn(ScrollDirection direction, string? selector = nul
/// .
///
/// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowOnBottom(string? selector = null) => ShowOn(ScrollDirection.Bottom, selector);
///
/// Specifies that the swap should show in the window by smoothly scrolling to either the top or bottom of the window.
///
- /// The direction to scroll the window after the swap.
///
/// This method adds the modifier show:window:, directing the swap to display the specified
/// element at the bottom of the window.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// The direction to scroll the window after the swap.
+ /// This object instance.
public SwapStyleBuilder ShowWindow(ScrollDirection direction)
{
switch (direction)
@@ -280,7 +284,7 @@ public SwapStyleBuilder ShowWindow(ScrollDirection direction)
/// for ensuring that important content or notifications at the top of the page are immediately visible to
/// the user after a swap operation.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowWindowTop() => ShowWindow(ScrollDirection.Top);
///
@@ -291,7 +295,7 @@ public SwapStyleBuilder ShowWindow(ScrollDirection direction)
/// at the bottom of the window following a swap by smoothly animating the scrollbar position. This positioning
/// can be used for infinite scrolling, footers, or information appended at the end of the page.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowWindowBottom() => ShowWindow(ScrollDirection.Bottom);
///
@@ -301,7 +305,7 @@ public SwapStyleBuilder ShowWindow(ScrollDirection direction)
/// This method disables automatic scrolling by setting the modifier show:none, ensuring the page
/// position remains unchanged after the swap.
///
- /// The SwapStyleBuilder instance for chaining.
+ /// This object instance.
public SwapStyleBuilder ShowNone()
{
AddModifier("show", "none");
@@ -309,17 +313,29 @@ public SwapStyleBuilder ShowNone()
return this;
}
+ ///
+ public override string ToString()
+ {
+ var (swapStyle, modifier) = Build();
+ var style = swapStyle.ToHtmxString();
+ var value = !string.IsNullOrWhiteSpace(modifier)
+ ? $"{style} {modifier}"
+ : style;
+ return value;
+ }
+
///
/// Builds the swap style command string with all specified modifiers.
///
- /// A tuple containing the SwapStyle and the constructed command string.
- internal (SwapStyle?, string) Build()
+ /// A tuple containing the and the constructed command string.
+ internal (SwapStyle, string) Build()
{
var value = string.Empty;
if (modifiers.Count > 0)
{
- value = modifiers.Cast()
+ value = modifiers
+ .Cast()
.Select(entry => $"{entry.Key}:{entry.Value}")
.Aggregate((current, next) => $"{current} {next}");
}
@@ -336,7 +352,7 @@ private void AddModifier(string modifier, string options)
{
if (modifiers.Contains(modifier))
modifiers.Remove(modifier);
-
+
modifiers.Add(modifier, options);
}
@@ -347,245 +363,3 @@ private void AddModifier(string modifier, string options)
///
private void AddModifier(string modifier, bool option) => AddModifier(modifier, option ? "true" : "false");
}
-
-///
-/// Extension methods for the SwapStyle enum to facilitate building swap style commands.
-///
-public static class SwapStyleBuilderExtension
-{
- ///
- /// Modifies the amount of time that htmx will wait after receiving a
- /// response to swap the content by including the modifier swap:.
- ///
- ///
- /// will be converted to milliseconds if less than 1000, otherwise seconds,
- /// meaning the resulting modifier will be swap:500ms for a of 500 milliseconds
- /// or swap:2s for a of 2 seconds..
- ///
- /// The swap style.
- /// The amount of time htmx should wait after receiving a
- /// response to swap the content.
- public static SwapStyleBuilder AfterSwapDelay(this SwapStyle style, TimeSpan time) => new SwapStyleBuilder(style).AfterSwapDelay(time);
-
- ///
- /// Modifies the amount of time that htmx will wait between the swap
- /// and the settle logic by including the modifier settle:.
- ///
- ///
- /// will be converted to milliseconds if less than 1000, otherwise seconds,
- /// meaning the resulting modifier will be settle:500ms for a of 500 milliseconds
- /// or settle:2s for a of 2 seconds..
- ///
- /// The swap style.
- /// The amount of time htmx should wait after receiving a
- /// response to swap the content.
- public static SwapStyleBuilder AfterSettleDelay(this SwapStyle style, TimeSpan time) => new SwapStyleBuilder(style).AfterSettleDelay(time);
-
- ///
- /// Specifies how to set the content scrollbar position after the swap and appends the modifier scroll:.
- ///
- ///
- /// Sets the swapped content scrollbar position after swapping immediately (without animation). For instance, using
- /// will add the modifier scroll:top which sets the scrollbar position to the top of swap content after the swap.
- /// If css is present then the page is scrolled to the of the content identified by the css selector.
- ///
- /// The swap style.
- /// The scroll direction after the swap.
- /// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder Scroll(this SwapStyle style, ScrollDirection direction, string? selector) => new SwapStyleBuilder(style).Scroll(direction, selector);
-
- ///
- /// Sets the content scrollbar position to the top of the swapped content after a swap.
- ///
- ///
- /// This method adds the modifier scroll:top to the swap commands, instructing the page to scroll to
- /// the top of the content after content is swapped immediately and without animation. If css
- /// is present then the page is scrolled to the top of the content identified by the css selector.
- ///
- /// Optional CSS selector of the target element.
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ScrollTop(this SwapStyle style, string? selector) => new SwapStyleBuilder(style).ScrollTop(selector);
-
- ///
- /// Sets the content scrollbar position to the bottom of the swapped content after a swap.
- ///
- ///
- /// This method adds the modifier scroll:bottom to the swap commands, instructing the page to scroll to
- /// the bottom of the content after content is swapped immediately and without animation. If css
- /// is present then the page is scrolled to the bottom of the content identified by the css selector.
- ///
- /// Optional CSS selector of the target element.
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ScrollBottom(this SwapStyle style, string? selector) => new SwapStyleBuilder(style).ScrollBottom(selector);
-
- ///
- /// Determines whether to ignore the document title in the swap response by appending the modifier
- /// ignoreTitle:.
- ///
- ///
- /// When set to true, the document title in the swap response will be ignored by adding the modifier
- /// ignoreTitle:true.
- /// This keeps the current title unchanged regardless of the incoming swap content's title tag.
- ///
- /// The swap style.
- /// Whether to ignore the title.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder IgnoreTitle(this SwapStyle style, bool ignore = true) => new SwapStyleBuilder(style).IgnoreTitle(ignore);
-
- ///
- /// Includes the document title from the swap response in the current page.
- ///
- ///
- /// This method ensures the title of the document is updated according to the swap response by removing any
- /// ignoreTitle modifiers, effectively setting ignoreTitle:false.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder IncludeTitle(this SwapStyle style) => new SwapStyleBuilder(style).IncludeTitle();
-
- ///
- /// Enables or disables transition effects for the swap by appending the modifier transition:{show}.
- ///
- ///
- /// Controls the display of transition effects during the swap. For example, setting to true
- /// will add the modifier transition:true to enable smooth transitions.
- ///
- /// The swap style.
- /// Whether to show transition effects.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder Transition(this SwapStyle style, bool show) => new SwapStyleBuilder(style).Transition(show);
-
- ///
- /// Explicitly includes transition effects for the swap.
- ///
- ///
- /// By calling this method, transition effects are enabled for the swap, adding the modifier transition:true.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder IncludeTransition(this SwapStyle style) => new SwapStyleBuilder(style).IncludeTransition();
-
- ///
- /// Explicitly ignores transition effects for the swap.
- ///
- ///
- /// This method disables transition effects by adding the modifier transition:false to the swap commands.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder IgnoreTransition(this SwapStyle style) => new SwapStyleBuilder(style).IgnoreTransition();
-
- ///
- /// Allows you to specify that htmx should scroll to the focused element when a request completes.
- /// htmx preserves focus between requests for inputs that have a defined id attribute. By
- /// default htmx prevents auto-scrolling to focused inputs between requests which can be
- /// unwanted behavior on longer requests when the user has already scrolled away.
- ///
- ///
- /// when true will be focus-scroll:true, otherwise when false
- /// will be focus-scroll:false
- ///
- /// The swap style.
- /// Whether to scroll to the focus element.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ScrollFocus(this SwapStyle style, bool scroll = true) => new SwapStyleBuilder(style).ScrollFocus(scroll);
-
- ///
- /// Explicitly preserves focus between requests for inputs that have a defined id attribute without
- /// scrolling.
- ///
- ///
- /// Adds a modifier of focus-scroll:false
- ///
- /// The swap style.
- /// Whether to scroll to current focus or preserve focus
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder PreserveFocus(this SwapStyle style, bool scroll = true) => new SwapStyleBuilder(style).PreserveFocus();
-
- ///
- /// Specifies a CSS selector to dynamically target for the swap operation, with a scroll direction after the swap.
- ///
- ///
- /// Adds a show modifier with the specified CSS selector and scroll direction. For example, if
- /// is ".item" and is , the modifier show:.item:top
- /// is added.
- ///
- /// The swap style.
- /// Optional CSS selector of the target element.
- /// The scroll direction after swap.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowOn(this SwapStyle style, ScrollDirection direction, string? selector = null) => new SwapStyleBuilder(style).ShowOn(direction, selector);
-
- ///
- /// Specifies that the swap should show the element matching the CSS selector at the top of the window.
- ///
- ///
- /// This method adds the modifier show:{selector}:top, directing the swap to display the specified element at the top of the window.
- ///
- /// The swap style.
- /// Optional CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowOnTop(this SwapStyle style, string? selector = null) => new SwapStyleBuilder(style).ShowOnTop(selector);
-
- ///
- /// Specifies that the swap should show the element matching the CSS selector at the bottom of the window.
- ///
- ///
- /// This method adds the modifier show:{selector}:bottom, directing the swap to display the specified element at the bottom of the window.
- ///
- /// The swap style.
- /// The CSS selector of the target element.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowOnBottom(this SwapStyle style, string? selector = null) => new SwapStyleBuilder(style).ShowOnBottom(selector);
-
- ///
- /// Specifies that the swap should show in the window by smoothly scrolling to either the top or bottom of the window.
- ///
- /// The direction to scroll the window after the swap.
- ///
- /// This method adds the modifier show:window:, directing the swap to display the specified
- /// element at the bottom of the window.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowWindow(this SwapStyle style, ScrollDirection direction) => new SwapStyleBuilder(style).ShowWindow(direction);
-
- ///
- /// Specifies that the swap should smoothly scroll to the top of the window.
- ///
- ///
- /// This method adds the modifier show:window:top, instructing the content to be displayed
- /// at the top of the window following a swap by smoothly animating the scrollbar position. This can be useful
- /// for ensuring that important content or notifications at the top of the page are immediately visible to
- /// the user after a swap operation.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowWindowTop(this SwapStyle style) => new SwapStyleBuilder(style).ShowWindowTop();
-
- ///
- /// Specifies that the swap should smoothly scroll to the bottom of the window.
- ///
- ///
- /// This method adds the modifier show:window:bottom, instructing the content to be displayed
- /// at the bottom of the window following a swap by smoothly animating the scrollbar position. This positioning
- /// can be used for infinite scrolling, footers, or information appended at the end of the page.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowWindowBottom(this SwapStyle style) => new SwapStyleBuilder(style).ShowWindowBottom();
-
- ///
- /// Turns off scrolling after swap.
- ///
- ///
- /// This method disables automatic scrolling by setting the modifier show:none, ensuring the page
- /// position remains unchanged after the swap.
- ///
- /// The swap style.
- /// The SwapStyleBuilder instance for chaining.
- public static SwapStyleBuilder ShowNone(this SwapStyle style) => new SwapStyleBuilder(style).ShowNone();
-}
\ No newline at end of file
diff --git a/src/Htmxor/Http/SwapStyleBuilderExtension.cs b/src/Htmxor/Http/SwapStyleBuilderExtension.cs
new file mode 100644
index 0000000..79ffa37
--- /dev/null
+++ b/src/Htmxor/Http/SwapStyleBuilderExtension.cs
@@ -0,0 +1,245 @@
+namespace Htmxor.Http;
+
+///
+/// Extension methods for the SwapStyle enum to facilitate building swap style commands.
+///
+public static class SwapStyleBuilderExtension
+{
+ ///
+ /// Modifies the amount of time that htmx will wait after receiving a
+ /// response to swap the content by including the modifier swap:.
+ ///
+ ///
+ /// will be converted to milliseconds if less than 1000, otherwise seconds,
+ /// meaning the resulting modifier will be swap:500ms for a of 500 milliseconds
+ /// or swap:2s for a of 2 seconds..
+ ///
+ /// The swap style.
+ /// The amount of time htmx should wait after receiving a
+ /// response to swap the content.
+ /// A object instance.
+ public static SwapStyleBuilder AfterSwapDelay(this SwapStyle style, TimeSpan time) => new SwapStyleBuilder(style).AfterSwapDelay(time);
+
+ ///
+ /// Modifies the amount of time that htmx will wait between the swap
+ /// and the settle logic by including the modifier settle:.
+ ///
+ ///
+ /// will be converted to milliseconds if less than 1000, otherwise seconds,
+ /// meaning the resulting modifier will be settle:500ms for a of 500 milliseconds
+ /// or settle:2s for a of 2 seconds..
+ ///
+ /// The swap style.
+ /// The amount of time htmx should wait after receiving a
+ /// response to swap the content.
+ /// A object instance.
+ public static SwapStyleBuilder AfterSettleDelay(this SwapStyle style, TimeSpan time) => new SwapStyleBuilder(style).AfterSettleDelay(time);
+
+ ///
+ /// Specifies how to set the content scrollbar position after the swap and appends the modifier scroll:.
+ ///
+ ///
+ /// Sets the swapped content scrollbar position after swapping immediately (without animation). For instance, using
+ /// will add the modifier scroll:top which sets the scrollbar position to the top of swap content after the swap.
+ /// If css is present then the page is scrolled to the of the content identified by the css selector.
+ ///
+ /// The swap style.
+ /// The scroll direction after the swap.
+ /// Optional CSS selector of the target element.
+ /// A object instance.
+ public static SwapStyleBuilder Scroll(this SwapStyle style, ScrollDirection direction, string? selector) => new SwapStyleBuilder(style).Scroll(direction, selector);
+
+ ///
+ /// Sets the content scrollbar position to the top of the swapped content after a swap.
+ ///
+ ///
+ /// This method adds the modifier scroll:top to the swap commands, instructing the page to scroll to
+ /// the top of the content after content is swapped immediately and without animation. If css
+ /// is present then the page is scrolled to the top of the content identified by the css selector.
+ ///
+ /// Optional CSS selector of the target element.
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ScrollTop(this SwapStyle style, string? selector) => new SwapStyleBuilder(style).ScrollTop(selector);
+
+ ///
+ /// Sets the content scrollbar position to the bottom of the swapped content after a swap.
+ ///
+ ///
+ /// This method adds the modifier scroll:bottom to the swap commands, instructing the page to scroll to
+ /// the bottom of the content after content is swapped immediately and without animation. If css
+ /// is present then the page is scrolled to the bottom of the content identified by the css selector.
+ ///
+ /// Optional CSS selector of the target element.
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ScrollBottom(this SwapStyle style, string? selector) => new SwapStyleBuilder(style).ScrollBottom(selector);
+
+ ///
+ /// Determines whether to ignore the document title in the swap response by appending the modifier
+ /// ignoreTitle:.
+ ///
+ ///
+ /// When set to true, the document title in the swap response will be ignored by adding the modifier
+ /// ignoreTitle:true.
+ /// This keeps the current title unchanged regardless of the incoming swap content's title tag.
+ ///
+ /// The swap style.
+ /// Whether to ignore the title.
+ /// A object instance.
+ public static SwapStyleBuilder IgnoreTitle(this SwapStyle style, bool ignore = true) => new SwapStyleBuilder(style).IgnoreTitle(ignore);
+
+ ///
+ /// Includes the document title from the swap response in the current page.
+ ///
+ ///
+ /// This method ensures the title of the document is updated according to the swap response by removing any
+ /// ignoreTitle modifiers, effectively setting ignoreTitle:false.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder IncludeTitle(this SwapStyle style) => new SwapStyleBuilder(style).IncludeTitle();
+
+ ///
+ /// Enables or disables transition effects for the swap by appending the modifier transition:{show}.
+ ///
+ ///
+ /// Controls the display of transition effects during the swap. For example, setting to true
+ /// will add the modifier transition:true to enable smooth transitions.
+ ///
+ /// The swap style.
+ /// Whether to show transition effects.
+ /// A object instance.
+ public static SwapStyleBuilder Transition(this SwapStyle style, bool show) => new SwapStyleBuilder(style).Transition(show);
+
+ ///
+ /// Explicitly includes transition effects for the swap.
+ ///
+ ///
+ /// By calling this method, transition effects are enabled for the swap, adding the modifier transition:true.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder IncludeTransition(this SwapStyle style) => new SwapStyleBuilder(style).IncludeTransition();
+
+ ///
+ /// Explicitly ignores transition effects for the swap.
+ ///
+ ///
+ /// This method disables transition effects by adding the modifier transition:false to the swap commands.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder IgnoreTransition(this SwapStyle style) => new SwapStyleBuilder(style).IgnoreTransition();
+
+ ///
+ /// Allows you to specify that htmx should scroll to the focused element when a request completes.
+ /// htmx preserves focus between requests for inputs that have a defined id attribute. By
+ /// default htmx prevents auto-scrolling to focused inputs between requests which can be
+ /// unwanted behavior on longer requests when the user has already scrolled away.
+ ///
+ ///
+ /// when true will be focus-scroll:true, otherwise when false
+ /// will be focus-scroll:false
+ ///
+ /// The swap style.
+ /// Whether to scroll to the focus element.
+ /// A object instance.
+ public static SwapStyleBuilder ScrollFocus(this SwapStyle style, bool scroll = true) => new SwapStyleBuilder(style).ScrollFocus(scroll);
+
+ ///
+ /// Explicitly preserves focus between requests for inputs that have a defined id attribute without
+ /// scrolling.
+ ///
+ ///
+ /// Adds a modifier of focus-scroll:false
+ ///
+ /// The swap style.
+ /// Whether to scroll to current focus or preserve focus
+ /// A object instance.
+ public static SwapStyleBuilder PreserveFocus(this SwapStyle style, bool scroll = true) => new SwapStyleBuilder(style).PreserveFocus();
+
+ ///
+ /// Specifies a CSS selector to dynamically target for the swap operation, with a scroll direction after the swap.
+ ///
+ ///
+ /// Adds a show modifier with the specified CSS selector and scroll direction. For example, if
+ /// is ".item" and is , the modifier show:.item:top
+ /// is added.
+ ///
+ /// The swap style.
+ /// Optional CSS selector of the target element.
+ /// The scroll direction after swap.
+ /// A object instance.
+ public static SwapStyleBuilder ShowOn(this SwapStyle style, ScrollDirection direction, string? selector = null) => new SwapStyleBuilder(style).ShowOn(direction, selector);
+
+ ///
+ /// Specifies that the swap should show the element matching the CSS selector at the top of the window.
+ ///
+ ///
+ /// This method adds the modifier show:{selector}:top, directing the swap to display the specified element at the top of the window.
+ ///
+ /// The swap style.
+ /// Optional CSS selector of the target element.
+ /// A object instance.
+ public static SwapStyleBuilder ShowOnTop(this SwapStyle style, string? selector = null) => new SwapStyleBuilder(style).ShowOnTop(selector);
+
+ ///
+ /// Specifies that the swap should show the element matching the CSS selector at the bottom of the window.
+ ///
+ ///
+ /// This method adds the modifier show:{selector}:bottom, directing the swap to display the specified element at the bottom of the window.
+ ///
+ /// The swap style.
+ /// The CSS selector of the target element.
+ /// A object instance.
+ public static SwapStyleBuilder ShowOnBottom(this SwapStyle style, string? selector = null) => new SwapStyleBuilder(style).ShowOnBottom(selector);
+
+ ///
+ /// Specifies that the swap should show in the window by smoothly scrolling to either the top or bottom of the window.
+ ///
+ /// The direction to scroll the window after the swap.
+ ///
+ /// This method adds the modifier show:window:, directing the swap to display the specified
+ /// element at the bottom of the window.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ShowWindow(this SwapStyle style, ScrollDirection direction) => new SwapStyleBuilder(style).ShowWindow(direction);
+
+ ///
+ /// Specifies that the swap should smoothly scroll to the top of the window.
+ ///
+ ///
+ /// This method adds the modifier show:window:top, instructing the content to be displayed
+ /// at the top of the window following a swap by smoothly animating the scrollbar position. This can be useful
+ /// for ensuring that important content or notifications at the top of the page are immediately visible to
+ /// the user after a swap operation.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ShowWindowTop(this SwapStyle style) => new SwapStyleBuilder(style).ShowWindowTop();
+
+ ///
+ /// Specifies that the swap should smoothly scroll to the bottom of the window.
+ ///
+ ///
+ /// This method adds the modifier show:window:bottom, instructing the content to be displayed
+ /// at the bottom of the window following a swap by smoothly animating the scrollbar position. This positioning
+ /// can be used for infinite scrolling, footers, or information appended at the end of the page.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ShowWindowBottom(this SwapStyle style) => new SwapStyleBuilder(style).ShowWindowBottom();
+
+ ///
+ /// Turns off scrolling after swap.
+ ///
+ ///
+ /// This method disables automatic scrolling by setting the modifier show:none, ensuring the page
+ /// position remains unchanged after the swap.
+ ///
+ /// The swap style.
+ /// A object instance.
+ public static SwapStyleBuilder ShowNone(this SwapStyle style) => new SwapStyleBuilder(style).ShowNone();
+}
diff --git a/src/Htmxor/Http/SwapStyleExtensions.cs b/src/Htmxor/Http/SwapStyleExtensions.cs
new file mode 100644
index 0000000..21f9e68
--- /dev/null
+++ b/src/Htmxor/Http/SwapStyleExtensions.cs
@@ -0,0 +1,29 @@
+using System.Runtime.CompilerServices;
+
+namespace Htmxor.Http;
+
+public static class SwapStyleExtensions
+{
+ ///
+ /// Converts the to their string version expected by htmx.
+ ///
+ /// The style to convert.
+ public static string ToHtmxString(this SwapStyle swapStyle)
+ {
+ var style = swapStyle switch
+ {
+ SwapStyle.InnerHTML => "innerHTML",
+ SwapStyle.OuterHTML => "outerHTML",
+ SwapStyle.BeforeBegin => "beforebegin",
+ SwapStyle.AfterBegin => "afterbegin",
+ SwapStyle.BeforeEnd => "beforeend",
+ SwapStyle.AfterEnd => "afterend",
+ SwapStyle.Delete => "delete",
+ SwapStyle.None => "none",
+ SwapStyle.Default => "",
+ _ => throw new SwitchExpressionException(swapStyle),
+ };
+
+ return style;
+ }
+}
\ No newline at end of file
diff --git a/src/Htmxor/SwapStyle.cs b/src/Htmxor/SwapStyle.cs
index 3ea8f5a..109dc2f 100644
--- a/src/Htmxor/SwapStyle.cs
+++ b/src/Htmxor/SwapStyle.cs
@@ -5,6 +5,12 @@
///
public enum SwapStyle
{
+ ///
+ /// Default style is what is specified in for the application
+ /// or htmx's default, which is .
+ ///
+ Default,
+
///
/// Replace the inner html of the target element.
///
diff --git a/test/Htmxor.Tests/Configuration/HtmxHeadOutletTest.cs b/test/Htmxor.Tests/Configuration/HtmxHeadOutletTest.cs
index c33846d..1a71d8e 100644
--- a/test/Htmxor.Tests/Configuration/HtmxHeadOutletTest.cs
+++ b/test/Htmxor.Tests/Configuration/HtmxHeadOutletTest.cs
@@ -90,4 +90,15 @@ public void HtmxConfig_serializer()
}
""");
}
+
+ [Fact]
+ public void HtmxConfig_default_swap_style_serializer()
+ {
+ var config = new HtmxConfig
+ {
+ DefaultSwapStyle = SwapStyle.Default,
+ };
+
+ config.DefaultSwapStyle.Should().BeNull();
+ }
}
diff --git a/test/Htmxor.Tests/Http/SwapStyleBuilderTests.cs b/test/Htmxor.Tests/Http/SwapStyleBuilderTests.cs
index 6f38856..96d6aea 100644
--- a/test/Htmxor.Tests/Http/SwapStyleBuilderTests.cs
+++ b/test/Htmxor.Tests/Http/SwapStyleBuilderTests.cs
@@ -191,11 +191,11 @@ public void SwapStyleBuilder_ShowWindow_BottomDirection_AddsCorrectModifier()
public void SwapStyleBuilder_NullSwapStyle_ReturnsNullStyle()
{
// Arrange & Act
- var builder = new SwapStyleBuilder(null);
+ var builder = new SwapStyleBuilder();
var (style, _) = builder.Build();
// Assert
- style.Should().BeNull();
+ style.Should().Be(SwapStyle.Default);
}
[Fact]