diff --git a/README.md b/README.md index a0d89ca..3490494 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,10 @@ If you want to load htmx from unpkg, `Htmx.Script.minified` or `Htmx.Script.unmi ## Feedback / Help -The author hangs out in the #htmx-general channel of the [htmx Discord server](https://htmx.org/discord) and the #web channel of the [F# Software Foundation's Slack server](https://fsharp.org/guides/slack/). +The author hangs out in the #dotnet-htmx channel (and most others) of the [htmx Discord server](https://htmx.org/discord) and the #web channel of the [F# Software Foundation's Slack server](https://fsharp.org/guides/slack/). ## Thanks -|[Giraffe logo](https://giraffe.wiki)|[htmx logo](https://htmx.org)|[JetBrains Logo (Main)](https://jb.gg/OpenSource)| -| :---: | :---: | :---: | -|for making ASP.NET Core functional|for making HTML cool again|for licensing their tools to this project| +|[Giraffe logo](https://giraffe.wiki)| [htmx logo](https://htmx.org) |[JetBrains Logo (Main)](https://jb.gg/OpenSource)| +| :---: |:------------------------------------------------------------------------------------------------------------------------------------:| :---: | +|for making ASP.NET Core functional| for making HTML cool again |for licensing their tools to this project| diff --git a/src/Common/Giraffe.Htmx.Common.fsproj b/src/Common/Giraffe.Htmx.Common.fsproj index dc835b3..df698f0 100644 --- a/src/Common/Giraffe.Htmx.Common.fsproj +++ b/src/Common/Giraffe.Htmx.Common.fsproj @@ -9,6 +9,7 @@ + diff --git a/src/Common/README.md b/src/Common/README.md index 28c0427..2dff994 100644 --- a/src/Common/README.md +++ b/src/Common/README.md @@ -2,4 +2,4 @@ This package contains common code shared between [`Giraffe.Htmx`](https://www.nuget.org/packages/Giraffe.Htmx) and [`Giraffe.ViewEngine.Htmx`](https://www.nuget.org/packages/Giraffe.ViewEngine.Htmx), and will be automatically installed when you install either one. -**htmx version: 1.9.8** +**htmx version: 1.9.10** diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f189553..4f48f8d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,8 +2,8 @@ net6.0;net7.0;net8.0 - 1.9.8 - Update script tags to pull htmx 1.9.8; add support for .NET 8 + 1.9.10 + Update script tags to pull htmx 1.9.10; add support for .NET 8 danieljsummers Bit Badger Solutions https://github.com/bit-badger/Giraffe.Htmx @@ -14,4 +14,9 @@ MIT Giraffe htmx - \ No newline at end of file + + + + + + diff --git a/src/Htmx/Giraffe.Htmx.fsproj b/src/Htmx/Giraffe.Htmx.fsproj index 09928ad..e195b98 100644 --- a/src/Htmx/Giraffe.Htmx.fsproj +++ b/src/Htmx/Giraffe.Htmx.fsproj @@ -9,10 +9,11 @@ + - + diff --git a/src/Htmx/README.md b/src/Htmx/README.md index 17b0539..8688751 100644 --- a/src/Htmx/README.md +++ b/src/Htmx/README.md @@ -2,7 +2,7 @@ This package enables server-side support for [htmx](https://htmx.org) within [Giraffe](https://giraffe.wiki) and ASP.NET's `HttpContext`. -**htmx version: 1.9.8** +**htmx version: 1.9.10** ### Setup diff --git a/src/Tests/ViewEngine.fs b/src/Tests/ViewEngine.fs index 8668302..5f0de7f 100644 --- a/src/Tests/ViewEngine.fs +++ b/src/Tests/ViewEngine.fs @@ -15,6 +15,399 @@ let hxEncoding = } ] +let hxEvent = + testList "HxEvent" [ + testList "Abort" [ + test "ToString succeeds" { + Expect.equal (string Abort) "abort" "Abort event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Abort.ToHxOnString()) "abort" "Abort hx-on event name not correct" + } + ] + testList "AfterOnLoad" [ + test "ToString succeeds" { + Expect.equal (string AfterOnLoad) "afterOnLoad" "AfterOnLoad event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterOnLoad.ToHxOnString()) "after-on-load" "AfterOnLoad hx-on event name not correct" + } + ] + testList "AfterProcessNode" [ + test "ToString succeeds" { + Expect.equal (string AfterProcessNode) "afterProcessNode" "AfterProcessNode event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (AfterProcessNode.ToHxOnString()) + "after-process-node" + "AfterProcessNode hx-on event name not correct" + } + ] + testList "AfterRequest" [ + test "ToString succeeds" { + Expect.equal (string AfterRequest) "afterRequest" "AfterRequest event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterRequest.ToHxOnString()) "after-request" "AfterRequest hx-on event name not correct" + } + ] + testList "AfterSettle" [ + test "ToString succeeds" { + Expect.equal (string AfterSettle) "afterSettle" "AfterSettle event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterSettle.ToHxOnString()) "after-settle" "AfterSettle hx-on event name not correct" + } + ] + testList "AfterSwap" [ + test "ToString succeeds" { + Expect.equal (string AfterSwap) "afterSwap" "AfterSwap event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (AfterSwap.ToHxOnString()) "after-swap" "AfterSwap hx-on event name not correct" + } + ] + testList "BeforeCleanupElement" [ + test "ToString succeeds" { + Expect.equal + (string BeforeCleanupElement) "beforeCleanupElement" "BeforeCleanupElement event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeCleanupElement.ToHxOnString()) + "before-cleanup-element" + "BeforeCleanupElement hx-on event name not correct" + } + ] + testList "BeforeOnLoad" [ + test "ToString succeeds" { + Expect.equal (string BeforeOnLoad) "beforeOnLoad" "BeforeOnLoad event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (BeforeOnLoad.ToHxOnString()) "before-on-load" "BeforeOnLoad hx-on event name not correct" + } + ] + testList "BeforeProcessNode" [ + test "ToString succeeds" { + Expect.equal (string BeforeProcessNode) "beforeProcessNode" "BeforeProcessNode event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeProcessNode.ToHxOnString()) + "before-process-node" + "BeforeProcessNode hx-on event name not correct" + } + ] + testList "BeforeRequest" [ + test "ToString succeeds" { + Expect.equal (string BeforeRequest) "beforeRequest" "BeforeRequest event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeRequest.ToHxOnString()) "before-request" "BeforeRequest hx-on event name not correct" + } + ] + testList "BeforeSwap" [ + test "ToString succeeds" { + Expect.equal (string BeforeSwap) "beforeSwap" "BeforeSwap event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (BeforeSwap.ToHxOnString()) "before-swap" "BeforeSwap hx-on event name not correct" + } + ] + testList "BeforeSend" [ + test "ToString succeeds" { + Expect.equal (string BeforeSend) "beforeSend" "BeforeSend event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (BeforeSend.ToHxOnString()) "before-send" "BeforeSend hx-on event name not correct" + } + ] + testList "ConfigRequest" [ + test "ToString succeeds" { + Expect.equal (string ConfigRequest) "configRequest" "ConfigRequest event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (ConfigRequest.ToHxOnString()) "config-request" "ConfigRequest hx-on event name not correct" + } + ] + testList "Confirm" [ + test "ToString succeeds" { + Expect.equal (string Confirm) "confirm" "Confirm event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Confirm.ToHxOnString()) "confirm" "Confirm hx-on event name not correct" + } + ] + testList "HistoryCacheError" [ + test "ToString succeeds" { + Expect.equal (string HistoryCacheError) "historyCacheError" "HistoryCacheError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (HistoryCacheError.ToHxOnString()) + "history-cache-error" + "HistoryCacheError hx-on event name not correct" + } + ] + testList "HistoryCacheMiss" [ + test "ToString succeeds" { + Expect.equal (string HistoryCacheMiss) "historyCacheMiss" "HistoryCacheMiss event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (HistoryCacheMiss.ToHxOnString()) + "history-cache-miss" + "HistoryCacheMiss hx-on event name not correct" + } + ] + testList "HistoryCacheMissError" [ + test "ToString succeeds" { + Expect.equal + (string HistoryCacheMissError) + "historyCacheMissError" + "HistoryCacheMissError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (HistoryCacheMissError.ToHxOnString()) + "history-cache-miss-error" + "HistoryCacheMissError hx-on event name not correct" + } + ] + testList "HistoryCacheMissLoad" [ + test "ToString succeeds" { + Expect.equal + (string HistoryCacheMissLoad) "historyCacheMissLoad" "HistoryCacheMissLoad event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (HistoryCacheMissLoad.ToHxOnString()) + "history-cache-miss-load" + "HistoryCacheMissLoad hx-on event name not correct" + } + ] + testList "HistoryRestore" [ + test "ToString succeeds" { + Expect.equal (string HistoryRestore) "historyRestore" "HistoryRestore event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (HistoryRestore.ToHxOnString()) "history-restore" "HistoryRestore hx-on event name not correct" + } + ] + testList "BeforeHistorySave" [ + test "ToString succeeds" { + Expect.equal (string BeforeHistorySave) "beforeHistorySave" "BeforeHistorySave event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (BeforeHistorySave.ToHxOnString()) + "before-history-save" + "BeforeHistorySave hx-on event name not correct" + } + ] + testList "Load" [ + test "ToString succeeds" { + Expect.equal (string Load) "load" "Load event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Load.ToHxOnString()) "load" "Load hx-on event name not correct" + } + ] + testList "NoSseSourceError" [ + test "ToString succeeds" { + Expect.equal (string NoSseSourceError) "noSSESourceError" "NoSseSourceError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (NoSseSourceError.ToHxOnString()) + "no-sse-source-error" + "NoSseSourceError hx-on event name not correct" + } + ] + testList "OnLoadError" [ + test "ToString succeeds" { + Expect.equal (string OnLoadError) "onLoadError" "OnLoadError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (OnLoadError.ToHxOnString()) "on-load-error" "OnLoadError hx-on event name not correct" + } + ] + testList "OobAfterSwap" [ + test "ToString succeeds" { + Expect.equal (string OobAfterSwap) "oobAfterSwap" "OobAfterSwap event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (OobAfterSwap.ToHxOnString()) "oob-after-swap" "OobAfterSwap hx-on event name not correct" + } + ] + testList "OobBeforeSwap" [ + test "ToString succeeds" { + Expect.equal (string OobBeforeSwap) "oobBeforeSwap" "OobBeforeSwap event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (OobBeforeSwap.ToHxOnString()) "oob-before-swap" "OobBeforeSwap hx-on event name not correct" + } + ] + testList "OobErrorNoTarget" [ + test "ToString succeeds" { + Expect.equal (string OobErrorNoTarget) "oobErrorNoTarget" "OobErrorNoTarget event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (OobErrorNoTarget.ToHxOnString()) + "oob-error-no-target" + "OobErrorNoTarget hx-on event name not correct" + } + ] + testList "Prompt" [ + test "ToString succeeds" { + Expect.equal (string Prompt) "prompt" "Prompt event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Prompt.ToHxOnString()) "prompt" "Prompt hx-on event name not correct" + } + ] + testList "PushedIntoHistory" [ + test "ToString succeeds" { + Expect.equal (string PushedIntoHistory) "pushedIntoHistory" "PushedIntoHistory event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (PushedIntoHistory.ToHxOnString()) + "pushed-into-history" + "PushedIntoHistory hx-on event name not correct" + } + ] + testList "ResponseError" [ + test "ToString succeeds" { + Expect.equal (string ResponseError) "responseError" "ResponseError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (ResponseError.ToHxOnString()) "response-error" "ResponseError hx-on event name not correct" + } + ] + testList "SendError" [ + test "ToString succeeds" { + Expect.equal (string SendError) "sendError" "SendError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (SendError.ToHxOnString()) "send-error" "SendError hx-on event name not correct" + } + ] + testList "SseError" [ + test "ToString succeeds" { + Expect.equal (string SseError) "sseError" "SseError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (SseError.ToHxOnString()) "sse-error" "SseError hx-on event name not correct" + } + ] + testList "SseOpen" [ + test "ToString succeeds" { + Expect.equal (string SseOpen) "sseOpen" "SseOpen event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (SseOpen.ToHxOnString()) "sse-open" "SseOpen hx-on event name not correct" + } + ] + testList "SwapError" [ + test "ToString succeeds" { + Expect.equal (string SwapError) "swapError" "SwapError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (SwapError.ToHxOnString()) "swap-error" "SwapError hx-on event name not correct" + } + ] + testList "TargetError" [ + test "ToString succeeds" { + Expect.equal (string TargetError) "targetError" "TargetError event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (TargetError.ToHxOnString()) "target-error" "TargetError hx-on event name not correct" + } + ] + testList "Timeout" [ + test "ToString succeeds" { + Expect.equal (string Timeout) "timeout" "Timeout event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (Timeout.ToHxOnString()) "timeout" "Timeout hx-on event name not correct" + } + ] + testList "ValidationValidate" [ + test "ToString succeeds" { + Expect.equal + (string ValidationValidate) "validation:validate" "ValidationValidate event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (ValidationValidate.ToHxOnString()) + "validation:validate" + "ValidationValidate hx-on event name not correct" + } + ] + testList "ValidationFailed" [ + test "ToString succeeds" { + Expect.equal (string ValidationFailed) "validation:failed" "ValidationFailed event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (ValidationFailed.ToHxOnString()) + "validation:failed" + "ValidationFailed hx-on event name not correct" + } + ] + testList "ValidationHalted" [ + test "ToString succeeds" { + Expect.equal (string ValidationHalted) "validation:halted" "ValidationHalted event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal + (ValidationHalted.ToHxOnString()) + "validation:halted" + "ValidationHalted hx-on event name not correct" + } + ] + testList "XhrAbort" [ + test "ToString succeeds" { + Expect.equal (string XhrAbort) "xhr:abort" "XhrAbort event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (XhrAbort.ToHxOnString()) "xhr:abort" "XhrAbort hx-on event name not correct" + } + ] + testList "XhrLoadEnd" [ + test "ToString succeeds" { + Expect.equal (string XhrLoadEnd) "xhr:loadend" "XhrLoadEnd event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (XhrLoadEnd.ToHxOnString()) "xhr:loadend" "XhrLoadEnd hx-on event name not correct" + } + ] + testList "XhrLoadStart" [ + test "ToString succeeds" { + Expect.equal (string XhrLoadStart) "xhr:loadstart" "XhrLoadStart event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (XhrLoadStart.ToHxOnString()) "xhr:loadstart" "XhrLoadStart hx-on event name not correct" + } + ] + testList "XhrProgress" [ + test "ToString succeeds" { + Expect.equal (string XhrProgress) "xhr:progress" "XhrProgress event name not correct" + } + test "ToHxOnString succeeds" { + Expect.equal (XhrProgress.ToHxOnString()) "xhr:progress" "XhrProgress hx-on event name not correct" + } + ] + + ] /// Tests for the HxHeaders module let hxHeaders = testList "HxHeaders" [ @@ -293,14 +686,14 @@ let hxVals = ] ] +/// Pipe-able assertion for a rendered node +let shouldRender expected node = + Expect.equal (RenderView.AsString.htmlNode node) expected "Rendered HTML incorrect" + /// Tests for the HtmxAttrs module let attributes = testList "Attributes" [ - /// Pipe-able assertion for a rendered node - let shouldRender expected node = - Expect.equal (RenderView.AsString.htmlNode node) expected "Rendered HTML incorrect" - test "_hxBoost succeeds" { div [ _hxBoost ] [] |> shouldRender """
""" } @@ -314,7 +707,7 @@ let attributes = p [ _hxDisable ] [] |> shouldRender """

""" } test "_hxDisabledElt succeeds" { - button [ _hxDiabledElt "this" ] [] |> shouldRender """""" + button [ _hxDisabledElt "this" ] [] |> shouldRender """""" } test "_hxDisinherit succeeds" { strong [ _hxDisinherit "*" ] [] |> shouldRender """""" @@ -347,10 +740,12 @@ let attributes = test "_hxNoBoost succeeds" { td [ _hxNoBoost ] [] |> shouldRender """""" } - test "_hxOn succeeds" { - let newLine = "\n" - strong [ _hxOn "submit: alert('oops')\nclick: alert('howdy!')" ] [] - |> shouldRender $"""""" + test "_hxOnEvent succeeds" { + a [ _hxOnEvent "click" "doThis()" ] [] |> shouldRender """""" + } + test "_hxOnHxEvent succeeds" { + strong [ _hxOnHxEvent BeforeSwap "changeStuff()" ] [] + |> shouldRender """""" } test "_hxParams succeeds" { br [ _hxParams "[p1,p2]" ] |> shouldRender """
""" @@ -425,14 +820,14 @@ let script = let html = RenderView.AsString.htmlNode Script.minified Expect.equal html - """""" + """""" "Minified script tag is incorrect" } test "unminified succeeds" { let html = RenderView.AsString.htmlNode Script.unminified Expect.equal html - """""" + """""" "Unminified script tag is incorrect" } ] @@ -584,7 +979,30 @@ let renderFragment = ] ] +#nowarn "44" + +/// Tests for the HtmxAttrs module +let deprecatedAttributes = + testList "Deprecated Attributes" [ + test "_hxOn succeeds" { + let newLine = "\n" + strong [ _hxOn "submit: alert('oops')\nclick: alert('howdy!')" ] [] + |> shouldRender $"""""" + } + ] + /// All tests in this module let allTests = - testList "ViewEngine.Htmx" - [ hxEncoding; hxHeaders; hxParams; hxRequest; hxTrigger; hxVals; attributes; script; renderFragment ] + testList "ViewEngine.Htmx" [ + hxEncoding + hxEvent + hxHeaders + hxParams + hxRequest + hxTrigger + hxVals + attributes + script + renderFragment + deprecatedAttributes + ] diff --git a/src/ViewEngine.Htmx/Giraffe.ViewEngine.Htmx.fsproj b/src/ViewEngine.Htmx/Giraffe.ViewEngine.Htmx.fsproj index 665b85c..3d120f3 100644 --- a/src/ViewEngine.Htmx/Giraffe.ViewEngine.Htmx.fsproj +++ b/src/ViewEngine.Htmx/Giraffe.ViewEngine.Htmx.fsproj @@ -9,6 +9,7 @@ + diff --git a/src/ViewEngine.Htmx/Htmx.fs b/src/ViewEngine.Htmx/Htmx.fs index 4b8a10c..f29f5c8 100644 --- a/src/ViewEngine.Htmx/Htmx.fs +++ b/src/ViewEngine.Htmx/Htmx.fs @@ -19,6 +19,146 @@ module HxEncoding = let MultipartForm = "multipart/form-data" +/// The events recognized by htmx +type HxEvent = + /// Send this event to an element to abort a request + | Abort + /// Triggered after an AJAX request has completed processing a successful response + | AfterOnLoad + /// Triggered after htmx has initialized a node + | AfterProcessNode + /// Triggered after an AJAX request has completed + | AfterRequest + /// Triggered after the DOM has settled + | AfterSettle + /// Triggered after new content has been swapped in + | AfterSwap + /// Triggered before htmx disables an element or removes it from the DOM + | BeforeCleanupElement + /// Triggered before any response processing occurs + | BeforeOnLoad + /// Triggered before htmx initializes a node + | BeforeProcessNode + /// Triggered before an AJAX request is made + | BeforeRequest + /// Triggered before a swap is done, allows you to configure the swap + | BeforeSwap + /// Triggered just before an ajax request is sent + | BeforeSend + /// Triggered before the request, allows you to customize parameters, headers + | ConfigRequest + /// Triggered after a trigger occurs on an element, allows you to cancel (or delay) issuing the AJAX request + | Confirm + /// Triggered on an error during cache writing + | HistoryCacheError + /// Triggered on a cache miss in the history subsystem + | HistoryCacheMiss + /// Triggered on a unsuccessful remote retrieval + | HistoryCacheMissError + /// Triggered on a successful remote retrieval + | HistoryCacheMissLoad + /// Triggered when htmx handles a history restoration action + | HistoryRestore + /// Triggered before content is saved to the history cache + | BeforeHistorySave + /// Triggered when new content is added to the DOM + | Load + /// Triggered when an element refers to a SSE event in its trigger, but no parent SSE source has been defined + | NoSseSourceError + /// Triggered when an exception occurs during the onLoad handling in htmx + | OnLoadError + /// Triggered after an out of band element as been swapped in + | OobAfterSwap + /// Triggered before an out of band element swap is done, allows you to configure the swap + | OobBeforeSwap + /// Triggered when an out of band element does not have a matching ID in the current DOM + | OobErrorNoTarget + /// Triggered after a prompt is shown + | Prompt + /// Triggered after an url is pushed into history + | PushedIntoHistory + /// Triggered when an HTTP response error (non-200 or 300 response code) occurs + | ResponseError + /// Triggered when a network error prevents an HTTP request from happening + | SendError + /// Triggered when an error occurs with a SSE source + | SseError + /// Triggered when a SSE source is opened + | SseOpen + /// Triggered when an error occurs during the swap phase + | SwapError + /// Triggered when an invalid target is specified + | TargetError + /// Triggered when a request timeout occurs + | Timeout + /// Triggered before an element is validated + | ValidationValidate + /// Triggered when an element fails validation + | ValidationFailed + /// Triggered when a request is halted due to validation errors + | ValidationHalted + /// Triggered when an ajax request aborts + | XhrAbort + /// Triggered when an ajax request ends + | XhrLoadEnd + /// Triggered when an ajax request starts + | XhrLoadStart + /// Triggered periodically during an ajax request that supports progress events + | XhrProgress + + /// The htmx event name (fst) and kebab-case name (snd, for use with hx-on) + static member private Values = Map [ + Abort, ("abort", "abort") + AfterOnLoad, ("afterOnLoad", "after-on-load") + AfterProcessNode, ("afterProcessNode", "after-process-node") + AfterRequest, ("afterRequest", "after-request") + AfterSettle, ("afterSettle", "after-settle") + AfterSwap, ("afterSwap", "after-swap") + BeforeCleanupElement, ("beforeCleanupElement", "before-cleanup-element") + BeforeOnLoad, ("beforeOnLoad", "before-on-load") + BeforeProcessNode, ("beforeProcessNode", "before-process-node") + BeforeRequest, ("beforeRequest", "before-request") + BeforeSwap, ("beforeSwap", "before-swap") + BeforeSend, ("beforeSend", "before-send") + ConfigRequest, ("configRequest", "config-request") + Confirm, ("confirm", "confirm") + HistoryCacheError, ("historyCacheError", "history-cache-error") + HistoryCacheMiss, ("historyCacheMiss", "history-cache-miss") + HistoryCacheMissError, ("historyCacheMissError", "history-cache-miss-error") + HistoryCacheMissLoad, ("historyCacheMissLoad", "history-cache-miss-load") + HistoryRestore, ("historyRestore", "history-restore") + BeforeHistorySave, ("beforeHistorySave", "before-history-save") + Load, ("load", "load") + NoSseSourceError, ("noSSESourceError", "no-sse-source-error") + OnLoadError, ("onLoadError", "on-load-error") + OobAfterSwap, ("oobAfterSwap", "oob-after-swap") + OobBeforeSwap, ("oobBeforeSwap", "oob-before-swap") + OobErrorNoTarget, ("oobErrorNoTarget", "oob-error-no-target") + Prompt, ("prompt", "prompt") + PushedIntoHistory, ("pushedIntoHistory", "pushed-into-history") + ResponseError, ("responseError", "response-error") + SendError, ("sendError", "send-error") + SseError, ("sseError", "sse-error") + SseOpen, ("sseOpen", "sse-open") + SwapError, ("swapError", "swap-error") + TargetError, ("targetError", "target-error") + Timeout, ("timeout", "timeout") + ValidationValidate, ("validation:validate", "validation:validate") + ValidationFailed, ("validation:failed", "validation:failed") + ValidationHalted, ("validation:halted", "validation:halted") + XhrAbort, ("xhr:abort", "xhr:abort") + XhrLoadEnd, ("xhr:loadend", "xhr:loadend") + XhrLoadStart, ("xhr:loadstart", "xhr:loadstart") + XhrProgress, ("xhr:progress", "xhr:progress") + ] + + /// The htmx event name + override this.ToString() = fst HxEvent.Values[this] + + /// The hx-on variant of the htmx event name + member this.ToHxOnString() = snd HxEvent.Values[this] + + /// Helper to create the `hx-headers` attribute [] module HxHeaders = @@ -176,6 +316,7 @@ module HxVals = /// Create values from a list of key/value pairs let From = toJson +open System /// Attributes and flags for htmx [] @@ -194,7 +335,7 @@ module HtmxAttrs = let _hxDisable = flag "hx-disable" /// Specifies elements that should be disabled when an htmx request is in flight - let _hxDiabledElt = attr "hx-disabled-elt" + let _hxDisabledElt = attr "hx-disabled-elt" /// Disinherit all ("*") or specific htmx attributes let _hxDisinherit = attr "hx-disinherit" @@ -227,8 +368,17 @@ module HtmxAttrs = let _hxNoBoost = attr "hx-boost" "false" /// Attach an event handler for DOM or htmx events + [] let _hxOn = attr "hx-on" + /// Attach an event handler for DOM events + let _hxOnEvent evtName = + attr $"hx-on:%s{evtName}" + + /// Attach an event handler for htmx events + let _hxOnHxEvent (hxEvent: HxEvent) = + _hxOnEvent $":{hxEvent.ToHxOnString()}" + /// Filters the parameters that will be submitted with a request let _hxParams = attr "hx-params" @@ -299,14 +449,14 @@ module Script = /// Script tag to load the minified version from unpkg.com let minified = - script [ _src "https://unpkg.com/htmx.org@1.9.8" - _integrity "sha384-rgjA7mptc2ETQqXoYC3/zJvkU7K/aP44Y+z7xQuJiVnB/422P/Ak+F/AqFR7E4Wr" + script [ _src "https://unpkg.com/htmx.org@1.9.10" + _integrity "sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" _crossorigin "anonymous" ] [] /// Script tag to load the unminified version from unpkg.com let unminified = - script [ _src "https://unpkg.com/htmx.org@1.9.8/dist/htmx.js" - _integrity "sha384-zOAIsdGekNHQVAjCjVrQ1xHoxyvnxgr63EH6IyXsCfvKZdRFRyG1u8GbWxO5oZ38" + script [ _src "https://unpkg.com/htmx.org@1.9.10/dist/htmx.js" + _integrity "sha384-j1TtLExqttdT7C3Z/rJy8UZcCGiuqwwN9++coZ6up+5O/l2FHdp3IGfuJOvst6d1" _crossorigin "anonymous" ] [] diff --git a/src/ViewEngine.Htmx/README.md b/src/ViewEngine.Htmx/README.md index f2a4778..ff9fa78 100644 --- a/src/ViewEngine.Htmx/README.md +++ b/src/ViewEngine.Htmx/README.md @@ -2,7 +2,7 @@ This package enables [htmx](https://htmx.org) support within the [Giraffe](https://giraffe.wiki) view engine. -**htmx version: 1.9.8** +**htmx version: 1.9.10** ### Setup diff --git a/src/icon.png b/src/icon.png new file mode 100644 index 0000000..9857f16 Binary files /dev/null and b/src/icon.png differ