v4, beta4 #19
@@ -103,3 +103,9 @@ module HxSwap =
|
||||
/// <seealso href="https://four.htmx.org/extensions/upsert">Extension</seealso>
|
||||
[<Literal>]
|
||||
let Upsert = "upsert"
|
||||
|
||||
/// <summary>Specify that the target of the htmx request should be downloaded</summary>
|
||||
/// <remarks>This requires the <c>hx-download</c> extension (included in the htmax bundle)</remarks>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-download#explicit-swap-style">Documentation</seealso>
|
||||
[<Literal>]
|
||||
let Download = "download"
|
||||
|
||||
@@ -30,6 +30,11 @@ type IHeaderDictionary with
|
||||
/// <summary><c>true</c> if the request is for history restoration after a miss in the local history cache</summary>
|
||||
member this.HxHistoryRestoreRequest
|
||||
with get () = hdr this "HX-History-Restore-Request" |> Option.map bool.Parse
|
||||
|
||||
/// <summary><c>true</c> if the request has been fired by the preload extension</summary>
|
||||
/// <remarks><c>preload</c> is part of the htmax htmx-plus-extensions bundle</remarks>
|
||||
member this.HxPreloaded
|
||||
with get () = hdr this "HX-Preloaded" |> Option.map bool.Parse
|
||||
|
||||
/// <summary>The user response to an <c>hx-prompt</c></summary>
|
||||
[<Obsolete "hx-prompt is removed in v4">]
|
||||
@@ -40,6 +45,11 @@ type IHeaderDictionary with
|
||||
member this.HxRequest
|
||||
with get () = hdr this "HX-Request" |> Option.map bool.Parse
|
||||
|
||||
/// <summary>The ID of the request (WebSocket extension requests only)</summary>
|
||||
/// <remarks><c>hx-ws</c> is part of the htmax htmx-plus-extensions bundle</remarks>
|
||||
member this.HxRequestId
|
||||
with get () = hdr this "HX-Request-ID"
|
||||
|
||||
/// <summary>The request type sent by htmx</summary>
|
||||
/// <seealso cref="HxRequestTypes" />
|
||||
member this.HxRequestType
|
||||
@@ -110,6 +120,14 @@ module Handlers =
|
||||
|
||||
open Giraffe.Htmx.Common
|
||||
|
||||
/// <summary>Instruct htmx to download a response from another path / URL</summary>
|
||||
/// <param name="path">The path or URL where the downloadable content is found</param>
|
||||
/// <returns>An HTTP handler with the <c>HX-Download</c> header set</returns>
|
||||
/// <remarks>This requires the client-side <c>hx-download</c> extension (included in the htmax bundle)</remarks>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-download#hx-download-header">Documentation</seealso>
|
||||
let withHxDownload (path: string) : HttpHandler =
|
||||
setHttpHeader "HX-Download" path
|
||||
|
||||
/// <summary>Instruct htmx to perform a client-side redirect for content</summary>
|
||||
/// <param name="path">The path where the content should be found</param>
|
||||
/// <returns>An HTTP handler with the <c>HX-Location</c> header set</returns>
|
||||
|
||||
@@ -63,6 +63,9 @@ let swap =
|
||||
test "Upsert is correct" {
|
||||
Expect.equal HxSwap.Upsert "upsert" "Upsert swap value incorrect"
|
||||
}
|
||||
test "Download is correct" {
|
||||
Expect.equal HxSwap.Download "download" "Download swap value incorrect"
|
||||
}
|
||||
]
|
||||
|
||||
/// All tests for this module
|
||||
|
||||
@@ -73,6 +73,30 @@ let dictExtensions =
|
||||
ctx.Request.Headers.HxHistoryRestoreRequest.Value "The header should have been false"
|
||||
}
|
||||
]
|
||||
testList "HxPreloaded" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxPreloaded "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present and true" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Preloaded", "true")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxPreloaded "There should be a header present"
|
||||
Expect.isTrue ctx.Request.Headers.HxPreloaded.Value "The header should have been true"
|
||||
}
|
||||
// This is not a condition fired by the extension; the header will be either absent or true
|
||||
test "succeeds when the header is present and false" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Preloaded", "false")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxPreloaded "There should be a header present"
|
||||
Expect.isFalse ctx.Request.Headers.HxPreloaded.Value "The header should have been false"
|
||||
}
|
||||
]
|
||||
testList "HxRequest" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
@@ -96,6 +120,21 @@ let dictExtensions =
|
||||
Expect.isFalse ctx.Request.Headers.HxRequest.Value "The header should have been false"
|
||||
}
|
||||
]
|
||||
testList "HxRequestId" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
ctx.Request.Headers.ReturnsForAnyArgs(HeaderDictionary()) |> ignore
|
||||
Expect.isNone ctx.Request.Headers.HxRequestId "There should not have been a header returned"
|
||||
}
|
||||
test "succeeds when the header is present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
dic.Add("HX-Request-ID", "abcd1234")
|
||||
ctx.Request.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
Expect.isSome ctx.Request.Headers.HxRequestId "There should be a header present"
|
||||
Expect.equal ctx.Request.Headers.HxRequestId.Value "abcd1234" "The header value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "HxRequestType" [
|
||||
test "succeeds when the header is not present" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
@@ -253,6 +292,14 @@ let next (ctx: HttpContext) = Task.FromResult(Some ctx)
|
||||
/// Tests for the HttpHandler functions provided in the Handlers module
|
||||
let handlers =
|
||||
testList "HandlerTests" [
|
||||
testTask "withHxDownload succeeds" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
ctx.Response.Headers.ReturnsForAnyArgs dic |> ignore
|
||||
let! _ = withHxDownload "/files/stuff.pdf" next ctx
|
||||
Expect.isTrue (dic.ContainsKey "HX-Download") "The HX-Download header should be present"
|
||||
Expect.equal dic["HX-Download"].[0] "/files/stuff.pdf" "The HX-Download value was incorrect"
|
||||
}
|
||||
testTask "withHxLocation succeeds" {
|
||||
let ctx = Substitute.For<HttpContext>()
|
||||
let dic = HeaderDictionary()
|
||||
|
||||
@@ -3,6 +3,118 @@ module ViewEngineMax
|
||||
open Expecto
|
||||
open Giraffe.ViewEngine.Htmax
|
||||
|
||||
/// Tests for the HxBrowserIndicatorConfigItem type
|
||||
let hxBrowserIndicatorConfigItem =
|
||||
testList "HxBrowserIndicatorConfigItem" [
|
||||
testList "ToHcon" [
|
||||
test "succeeds for BoostBrowserIndicator" {
|
||||
Expect.equal
|
||||
((BoostBrowserIndicator false).ToHcon())
|
||||
"boostBrowserIndicator:false"
|
||||
"The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the HxPreloadConfigItem type
|
||||
let hxPreloadConfigItem =
|
||||
testList "HxPreloadConfigItem" [
|
||||
testList "ToHcon" [
|
||||
test "succeeds for AutoBoost" {
|
||||
Expect.equal ((AutoBoost false).ToHcon()) "autoBoost:false" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for BoostEvent" {
|
||||
Expect.equal ((BoostEvent "mouseover").ToHcon()) "boostEvent:mouseover" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for BoostTimeout" {
|
||||
Expect.equal ((BoostTimeout 30_000).ToHcon()) "boostTimeout:30000" "The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the HxSseWsConfigItem type
|
||||
let hxSseWsConfigItem =
|
||||
testList "HxSseWsConfigItem" [
|
||||
testList "ToHcon" [
|
||||
test "succeeds for Reconnect" {
|
||||
Expect.equal ((Reconnect true).ToHcon()) "reconnect:true" "The HCON value was incorrect"
|
||||
}
|
||||
testList "ReconnectDelay" [
|
||||
test "succeeds for numeric value" {
|
||||
Expect.equal ((ReconnectDelay "3000").ToHcon()) "reconnectDelay:3000" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for value with units" {
|
||||
Expect.equal ((ReconnectDelay "3s").ToHcon()) "reconnectDelay:3s" "The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "ReconnectMaxDelay" [
|
||||
test "succeeds for numeric value" {
|
||||
Expect.equal
|
||||
((ReconnectMaxDelay "30000").ToHcon()) "reconnectMaxDelay:30000" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for value with units" {
|
||||
Expect.equal
|
||||
((ReconnectMaxDelay "50s").ToHcon()) "reconnectMaxDelay:50s" "The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
testList "ReconnectMaxAttempts" [
|
||||
test "succeeds for negative 1" {
|
||||
Expect.equal
|
||||
((ReconnectMaxAttempts -1).ToHcon())
|
||||
"reconnectMaxAttempts:Infinity"
|
||||
"The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for zero" {
|
||||
Expect.equal
|
||||
((ReconnectMaxAttempts 0).ToHcon()) "reconnectMaxAttempts:0" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for positive number" {
|
||||
Expect.equal
|
||||
((ReconnectMaxAttempts 7).ToHcon()) "reconnectMaxAttempts:7" "The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
test "succeeds for ReconnectJitter" {
|
||||
Expect.equal ((ReconnectJitter 0.7).ToHcon()) "reconnectJitter:0.7" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for PauseOnBackground" {
|
||||
Expect.equal
|
||||
((PauseOnBackground false).ToHcon()) "pauseOnBackground:false" "The HCON value was incorrect"
|
||||
}
|
||||
test "succeeds for PendingRequestTtl" {
|
||||
Expect.equal ((PendingRequestTtl 5000).ToHcon()) "pendingRequestTTL:5000" "The HCON value was incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the HxConfig module
|
||||
let hxConfig =
|
||||
testList "HxConfig" [
|
||||
test "hxBrowserIndicatorConfig succeeds" {
|
||||
Expect.equal
|
||||
(hxBrowserIndicatorConfig [ BoostBrowserIndicator true ])
|
||||
"browser-indicator.boostBrowserIndicator:true"
|
||||
"Config settings not correct"
|
||||
}
|
||||
test "hxPreloadConfig succeeds" {
|
||||
Expect.equal
|
||||
(hxPreloadConfig [ AutoBoost true; BoostTimeout 3_000 ])
|
||||
"preload.autoBoost:true preload.boostTimeout:3000"
|
||||
"Config settings not correct"
|
||||
}
|
||||
test "hxSseConfig succeeds" {
|
||||
Expect.equal
|
||||
(hxSseConfig [ ReconnectDelay "5s"; PauseOnBackground false ])
|
||||
"sse.reconnectDelay:5s sse.pauseOnBackground:false"
|
||||
"Config settings not correct"
|
||||
}
|
||||
test "hxWsConfig succeeds" {
|
||||
Expect.equal
|
||||
(hxWsConfig [ Reconnect false; PendingRequestTtl 40_000 ])
|
||||
"ws.reconnect:false ws.pendingRequestTTL:40000"
|
||||
"Config settings not correct"
|
||||
}
|
||||
]
|
||||
|
||||
/// Tests for the HxEvent module
|
||||
let hxEvent =
|
||||
testList "HxEvent" [
|
||||
@@ -110,6 +222,37 @@ let hxEvent =
|
||||
(BeforeWsRequest.ToHxOnString()) "before:ws:request" "BeforeWsRequest hx-on event name not correct"
|
||||
}
|
||||
]
|
||||
testList "DownloadComplete" [
|
||||
test "ToString succeeds" {
|
||||
Expect.equal (string DownloadComplete) "downloadComplete" "DownloadComplete event name not correct"
|
||||
}
|
||||
test "ToHxOnString succeeds" {
|
||||
Expect.equal
|
||||
(DownloadComplete.ToHxOnString())
|
||||
"download:complete"
|
||||
"DownloadComplete hx-on event name not correct"
|
||||
}
|
||||
]
|
||||
testList "DownloadProgress" [
|
||||
test "ToString succeeds" {
|
||||
Expect.equal (string DownloadProgress) "downloadProgress" "DownloadProgress event name not correct"
|
||||
}
|
||||
test "ToHxOnString succeeds" {
|
||||
Expect.equal
|
||||
(DownloadProgress.ToHxOnString())
|
||||
"download:progress"
|
||||
"DownloadProgress hx-on event name not correct"
|
||||
}
|
||||
]
|
||||
testList "DownloadStart" [
|
||||
test "ToString succeeds" {
|
||||
Expect.equal (string DownloadStart) "downloadStart" "DownloadStart event name not correct"
|
||||
}
|
||||
test "ToHxOnString succeeds" {
|
||||
Expect.equal
|
||||
(DownloadStart.ToHxOnString()) "download:start" "DownloadStart hx-on event name not correct"
|
||||
}
|
||||
]
|
||||
testList "SseClose" [
|
||||
test "ToString succeeds" {
|
||||
Expect.equal (string SseClose) "sseClose" "SseClose event name not correct"
|
||||
@@ -138,10 +281,25 @@ let shouldRender expected node =
|
||||
let attributes =
|
||||
testList "Attributes" [
|
||||
|
||||
test "_hxBrowserIndicator succeeds" {
|
||||
a [ _hxBrowserIndicator ] [] |> shouldRender """<a hx-browser-indicator="true"></a>"""
|
||||
}
|
||||
test "_hxLive succeeds" {
|
||||
main [ _hxLive "q().doStuff()" ] [] |> shouldRender """<main hx-live="q().doStuff()"></main>"""
|
||||
}
|
||||
test "_hxOnMax succeeds" {
|
||||
body [ _hxOnMax SseClose "alert(done)" ] []
|
||||
|> shouldRender """<body hx-on:htmx:sse:close="alert(done)"></body>"""
|
||||
}
|
||||
testList "_hxPreload" [
|
||||
test "succeeds when given an event" {
|
||||
blockquote [ _hxPreload (Some "focus") ] []
|
||||
|> shouldRender """<blockquote hx-preload="focus"></blockquote>"""
|
||||
}
|
||||
test "succeeds when not given an event" {
|
||||
em [ _hxPreload None ] [] |> shouldRender """<em hx-preload></em>"""
|
||||
}
|
||||
]
|
||||
test "_hxSseClose succeeds" {
|
||||
form [ _hxSseClose "fin" ] [] |> shouldRender """<form hx-sse:close="fin"></form>"""
|
||||
}
|
||||
@@ -149,6 +307,9 @@ let attributes =
|
||||
div [ _hxSseConnect "/path/to/resource" ] []
|
||||
|> shouldRender """<div hx-sse:connect="/path/to/resource"></div>"""
|
||||
}
|
||||
test "_hxTargets succeeds" {
|
||||
dl [ _hxTargets ".ephemeral" ] [] |> shouldRender """<dl hx-targets=".ephemeral"></dl>"""
|
||||
}
|
||||
test "_hxWsConnect succeeds" {
|
||||
p [ _hxWsConnect "/over/here" ] [] |> shouldRender """<p hx-ws:connect="/over/here"></p>"""
|
||||
}
|
||||
@@ -165,6 +326,10 @@ let attributes =
|
||||
|
||||
let allTests =
|
||||
testList "ViewEngine.Htmax" [
|
||||
hxBrowserIndicatorConfigItem
|
||||
hxPreloadConfigItem
|
||||
hxSseWsConfigItem
|
||||
hxConfig
|
||||
hxEvent
|
||||
attributes
|
||||
]
|
||||
|
||||
@@ -1,6 +1,104 @@
|
||||
/// <summary>Types and functions supporting htmax-bundled extension attributes in Giraffe View Engine</summary>
|
||||
module Giraffe.ViewEngine.Htmax
|
||||
|
||||
/// <summary>Items which can be configured for the <c>hx-browser-indicator</c> extension</summary>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-browser-indicator#boosted-elements">Documentation</seealso>
|
||||
type HxBrowserIndicatorConfigItem =
|
||||
/// <summary>Whether to show the browser's native loading indicator for <c>hx-boost</c>ed links</summary>
|
||||
| BoostBrowserIndicator of bool
|
||||
|
||||
/// <summary>Get the HCON representation of this configuration value</summary>
|
||||
member this.ToHcon() =
|
||||
match this with
|
||||
| BoostBrowserIndicator it -> "boostBrowserIndicator:" + (string it).ToLowerInvariant()
|
||||
|
||||
|
||||
/// <summary>Items which can be configured for the <c>hx-preload</c> extension</summary>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-preload#configuration">Documentation</seealso>
|
||||
type HxPreloadConfigItem =
|
||||
/// <summary>Whether items subject to <c>hx-boost</c> are automatically preloaded (default <c>true</c>)</summary>
|
||||
| AutoBoost of bool
|
||||
|
||||
/// <summary>The event to use for <c>hx-boost</c> auto-preloaded content (default "mousedown")</summary>
|
||||
| BoostEvent of string
|
||||
|
||||
/// <summary>The timeout (in ms) for <c>hx-boost</c> auto-preloaded requests (default 50_000)</summary>
|
||||
| BoostTimeout of int
|
||||
|
||||
/// <summary>Get the HCON representation of this configuration value</summary>
|
||||
member this.ToHcon() =
|
||||
match this with
|
||||
| AutoBoost it -> "autoBoost:" + (string it).ToLowerInvariant()
|
||||
| BoostEvent it -> $"boostEvent:{it}"
|
||||
| BoostTimeout it -> $"boostTimeout:{it}"
|
||||
|
||||
|
||||
/// <summary>Items which can be configured for the <c>hx-sse</c> or <c>hx-ws</c> extensions</summary>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-sse#configuration">SSE Documentation</seealso>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-ws#configuration">WebSockets Documentation</seealso>
|
||||
type HxSseWsConfigItem =
|
||||
/// <summary>Whether to automatically reconnect on stream end (default <c>true</c>)</summary>
|
||||
| Reconnect of bool
|
||||
|
||||
/// <summary>Delay for reconnect attempts (ms, or numbers with units "1s", "2m"; default "500")</summary>
|
||||
| ReconnectDelay of string
|
||||
|
||||
/// <summary>Maximum delay for reconnect attempts (ms, or numbers with units "1s, "2m"; default "60000")</summary>
|
||||
| ReconnectMaxDelay of string
|
||||
|
||||
/// <summary>Reconnect maximum attempts (use -1 for Infinity; default Infinity)</summary>
|
||||
| ReconnectMaxAttempts of int
|
||||
|
||||
/// <summary>Jitter to use when reconnecting (decimal between 0.0 and 1.0; default 0.3)</summary>
|
||||
| ReconnectJitter of double
|
||||
|
||||
/// <summary>Whether to pause when the current tab is in the background (default <c>true</c>)</summary>
|
||||
| PauseOnBackground of bool
|
||||
|
||||
/// <summary>Time-to-Live (TTL) for pending requests (<c>hx-ws</c> only)</summary>
|
||||
| PendingRequestTtl of int
|
||||
|
||||
/// <summary>Get the HCON representation of this configuration value</summary>
|
||||
member this.ToHcon() =
|
||||
match this with
|
||||
| Reconnect it -> "reconnect:" + (string it).ToLowerInvariant()
|
||||
| ReconnectDelay it -> $"reconnectDelay:{it}"
|
||||
| ReconnectMaxDelay it -> $"reconnectMaxDelay:{it}"
|
||||
| ReconnectMaxAttempts it -> "reconnectMaxAttempts:" + if it = -1 then "Infinity" else string it
|
||||
| ReconnectJitter it -> $"reconnectJitter:{it}"
|
||||
| PauseOnBackground it -> "pauseOnBackground:" + (string it).ToLowerInvariant()
|
||||
| PendingRequestTtl it -> $"pendingRequestTTL:{it}"
|
||||
|
||||
|
||||
/// <summary>Helpers for generating extension configuration parameters</summary>
|
||||
[<AutoOpen>]
|
||||
module HxConfig =
|
||||
|
||||
/// Create an HCON section suitable for hx-config
|
||||
let private hconSettings title values =
|
||||
values |> Seq.map (sprintf "%s.%s" title) |> String.concat " "
|
||||
|
||||
/// <summary>Generate configuration items for preload suitable for <c>hx-config</c></summary>
|
||||
/// <param name="items">The configuration items</param>
|
||||
let hxBrowserIndicatorConfig (items: HxBrowserIndicatorConfigItem seq) =
|
||||
items |> Seq.map _.ToHcon() |> hconSettings "browser-indicator"
|
||||
|
||||
/// <summary>Generate configuration items for preload suitable for <c>hx-config</c></summary>
|
||||
/// <param name="items">The configuration items</param>
|
||||
let hxPreloadConfig (items: HxPreloadConfigItem seq) =
|
||||
items |> Seq.map _.ToHcon() |> hconSettings "preload"
|
||||
|
||||
/// <summary>Generate configuration items for SSE suitable for <c>hx-config</c></summary>
|
||||
/// <param name="items">The configuration items</param>
|
||||
let hxSseConfig (items: HxSseWsConfigItem seq) =
|
||||
items |> Seq.map _.ToHcon() |> hconSettings "sse"
|
||||
|
||||
/// <summary>Generate configuration items for WebSockets suitable for <c>hx-config</c></summary>
|
||||
/// <param name="items">The configuration items</param>
|
||||
let hxWsConfig (items: HxSseWsConfigItem seq) =
|
||||
items |> Seq.map _.ToHcon() |> hconSettings "ws"
|
||||
|
||||
|
||||
/// <summary>The events recognized by htmax-bundled extensions</summary>
|
||||
[<Struct>]
|
||||
type HxEvent =
|
||||
@@ -29,6 +127,15 @@ type HxEvent =
|
||||
/// <summary>Fired before a WebSocket connection is established (cancelable)</summary>
|
||||
| BeforeWsConnection
|
||||
|
||||
/// <summary>Fired when a download handled by <c>hx-download</c> is complete</summary>
|
||||
| DownloadComplete
|
||||
|
||||
/// <summary>Fired when a download handled by <c>hx-download</c> is complete</summary>
|
||||
| DownloadProgress
|
||||
|
||||
/// <summary>Fired when a chunk is received for a download handled by <c>hx-download</c></summary>
|
||||
| DownloadStart
|
||||
|
||||
/// <summary>Fired before a received WebSocket message is processed (cancelable)</summary>
|
||||
| BeforeWsMessage
|
||||
|
||||
@@ -53,6 +160,9 @@ type HxEvent =
|
||||
BeforeWsConnection, ("beforeWsConnection", "before:ws:connection")
|
||||
BeforeWsMessage, ("beforeWsMessage", "before:ws:message")
|
||||
BeforeWsRequest, ("beforeWsRequest", "before:ws:request")
|
||||
DownloadComplete, ("downloadComplete", "download:complete")
|
||||
DownloadProgress, ("downloadProgress", "download:progress")
|
||||
DownloadStart, ("downloadStart", "download:start")
|
||||
SseClose, ("sseClose", "sse:close")
|
||||
SseError, ("sseError", "sse:error")
|
||||
]
|
||||
@@ -68,6 +178,19 @@ type HxEvent =
|
||||
[<AutoOpen>]
|
||||
module HtmaxAttrs =
|
||||
|
||||
/// <summary>Display the browser's native loading indicator when an htmx request is in flight</summary>
|
||||
/// <returns>A configured <c>hx-browser-indicator</c> attribute</returns>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-browser-indicator#usage">Documentation</seealso>
|
||||
let _hxBrowserIndicator =
|
||||
attr "hx-browser-indicator" "true"
|
||||
|
||||
/// <summary>Run script each time the DOM changes</summary>
|
||||
/// <param name="script">The script to be run each time the DOM changes (may use <c>q</c> helper)</param>
|
||||
/// <returns>A configured <c>hx-live</c> attribute</returns>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-live#the-hx-live-attribute">Documentation</seealso>
|
||||
let _hxLive script =
|
||||
attr "hx-live" script
|
||||
|
||||
/// <summary>Generate an <c>hx-on:htmx</c> event for an htmax-bundled extension event</summary>
|
||||
/// <param name="event">The <c>HxEvent</c> to be handled</param>
|
||||
/// <param name="handler">The script to be executed when the event occurs</param>
|
||||
@@ -76,6 +199,14 @@ module HtmaxAttrs =
|
||||
let _hxOnMax (event: HxEvent) handler =
|
||||
Htmx.HtmxAttrs._hxOnEvent $"htmx:{event.ToHxOnString()}" handler
|
||||
|
||||
/// <summary>Identify a resource as one that should be preloaded</summary>
|
||||
/// <param name="evt">The DOM event or htmx trigger which should cause the preload (optional; default behavior is
|
||||
/// preloading on <c>mousedown</c>)</param>
|
||||
/// <returns>A configured <c>hx-preload</c> attribute</returns>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-preload#usage">Documentation</seealso>
|
||||
let _hxPreload evt =
|
||||
match evt with Some it -> attr "hx-preload" it | None -> flag "hx-preload"
|
||||
|
||||
/// <summary>Define an SSE message which indicates the connection should be closed</summary>
|
||||
/// <param name="message">The text of the message which indicates the SSE connection should be closed</param>
|
||||
/// <returns>A configured <c>hx-sse:close</c> attribute</returns>
|
||||
@@ -90,6 +221,13 @@ module HtmaxAttrs =
|
||||
let _hxSseConnect url =
|
||||
attr "hx-sse:connect" url
|
||||
|
||||
/// <summary>Replace multiple targets with the same content</summary>
|
||||
/// <param name="selector">The CSS selector to identify targets for the replacement</param>
|
||||
/// <returns>A configured <c>hx-targets</c> attribute</returns>
|
||||
/// <seealso href="https://four.htmx.org/extensions/hx-targets#usage">Documentation</seealso>
|
||||
let _hxTargets selector =
|
||||
attr "hx-targets" selector
|
||||
|
||||
/// <summary>Connect to a WebSocket URL</summary>
|
||||
/// <param name="url">The URL to which a WebSocket connection should be established</param>
|
||||
/// <returns>A configured <c>hx-ws:connect</c> attribute</returns>
|
||||
|
||||
@@ -93,7 +93,7 @@ type HxEvent =
|
||||
| [<System.Obsolete "Removed in v4; use Htmax.HxEvents.AfterSseMessage">] AfterSseMessage
|
||||
|
||||
/// <summary>Triggered after a Server Sent Events (SSE) stream is closed</summary>
|
||||
| [<System.Obsolete "Removed in v4; SSE streaming not a function of SSE extension">] AfterSseStream
|
||||
| [<System.Obsolete "Removed in v4; SSE is assumed to be a stream">] AfterSseStream
|
||||
|
||||
/// <summary>Triggered after new content has been swapped in</summary>
|
||||
| AfterSwap
|
||||
@@ -144,7 +144,7 @@ type HxEvent =
|
||||
| [<System.Obsolete "Removed in v4; use fetch event handlers">] BeforeSseReconnect
|
||||
|
||||
/// <summary>Triggered before a Server Sent Events (SSE) stream is opened</summary>
|
||||
| [<System.Obsolete "Removed in v4; SSE streaming not a function of SSE extension">] BeforeSseStream
|
||||
| [<System.Obsolete "Removed in v4; SSE is assumed to be a stream">] BeforeSseStream
|
||||
|
||||
/// <summary>Triggered before a swap is done, allows you to configure the swap</summary>
|
||||
| BeforeSwap
|
||||
|
||||
Reference in New Issue
Block a user