diff --git a/.vscode/settings.json b/.vscode/settings.json
index 2fbef1d..ff9bc79 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,5 @@
{
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"],
- "cSpell.words": ["classtools", "gomponents"]
+ "cSpell.words": ["classtools", "eventheader", "templ", "gomponents"]
}
diff --git a/README.md b/README.md
index aa962fa..438fafa 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,8 @@ See [htmx/ext](./htmx/ext) for a full list of extensions.
- [`class-tools`](https://htmx.org/extensions/class-tools/)
- [`preload`](https://htmx.org/extensions/preload/)
+- [`response-targets`](https://htmx.org/extensions/response-targets/)
+- [`event-header`](https://htmx.org/extensions/event-header/)
- [`remove-me`](https://htmx.org/extensions/remove-me/)
## Examples
diff --git a/htmx/ext/eventheader/eventheader.go b/htmx/ext/eventheader/eventheader.go
new file mode 100644
index 0000000..da0b212
--- /dev/null
+++ b/htmx/ext/eventheader/eventheader.go
@@ -0,0 +1,24 @@
+// package eventheader the Triggering-Event header to requests. The value of the header is a JSON serialized version of the event that triggered the request.
+//
+// # Install
+//
+//
+//
+// # Usage
+//
+//
+//
+// Sends something like this:
+//
+// Triggering-Event: '{ "isTrusted": false, "htmx-internal-data": { "handled": true }, "screenX": 0, "screenY": 0, "clientX": 0, "clientY": 0, "ctrlKey": false, "shiftKey": false, "altKey": false, "metaKey": false, "button": 0, "buttons": 0, "relatedTarget": null, "pageX": 0, "pageY": 0, "x": 0, "y": 0, "offsetX": 0, "offsetY": 0, "movementX": 0, "movementY": 0, "fromElement": null, "toElement": "button", "layerX": 0, "layerY": 0, "view": "Window", "detail": 0, "sourceCapabilities": null, "which": 1, "NONE": 0, "CAPTURING_PHASE": 1, "AT_TARGET": 2, "BUBBLING_PHASE": 3, "type": "click", "target": "button", "currentTarget": "button", "eventPhase": 2, "bubbles": true, "cancelable": true, "defaultPrevented": true, "composed": true, "timeStamp": 188.86999995447695, "srcElement": "button", "returnValue": false, "cancelBubble": false, "path": [ "button", "div#work-area", "body", "html", "Node", "Window" ] }'
+//
+// Extension: [event-header]
+//
+// [event-header]: https://htmx.org/extensions/event-header/
+package eventheader
+
+import "github.com/will-wow/typed-htmx-go/htmx"
+
+const Extension htmx.Extension = "event-header"
diff --git a/htmx/ext/responsetargets/responsetargets.go b/htmx/ext/responsetargets/responsetargets.go
new file mode 100644
index 0000000..efb9461
--- /dev/null
+++ b/htmx/ext/responsetargets/responsetargets.go
@@ -0,0 +1,102 @@
+// package responsetargets allows you to specify different target elements to be swapped when different HTTP response codes are received.
+//
+// # Install
+//
+//
+//
+// Extension: [response-targets]
+//
+// [response-targets]: https://htmx.org/extensions/response-targets/
+package responsetargets
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/will-wow/typed-htmx-go/htmx"
+)
+
+// Extension allows you to specify different target elements to be swapped when different HTTP response codes are received.
+//
+// # Install
+//
+//
+//
+// Extension: [response-targets]
+//
+// [response-targets]: https://htmx.org/extensions/response-targets/
+const Extension htmx.Extension = "response-targets"
+
+// A Code is a complete or partial HTTP response code.
+type Code interface {
+ code() string
+}
+
+// A Status is a complete HTTP response code. You can wrap the http.Status* constants with [Status].
+type Status int
+
+var _ Code = Status(0)
+
+func (s Status) code() string {
+ return strconv.Itoa(int(s))
+}
+
+// an errorCode is the string "error", used to cover all 4xx and 5xx HTTP response codes.
+type errorCode string
+
+var _ Code = errorCode("")
+
+// Error is a status code that covers all 4xx and 5xx HTTP response codes.
+const Error errorCode = "error"
+
+func (e errorCode) code() string {
+ return string(e)
+}
+
+// A wildcard is a partial HTTP response code with a wildcard component.
+type wildcard []int
+
+var _ Code = (wildcard)(nil)
+
+// Wildcard creates a wildcard code with the given digits.
+// For example, Wildcard(4, 1) results in hx-target-41*, and matches all 41x HTTP response codes.
+func Wildcard(digits ...int) wildcard {
+ return digits
+}
+
+func (w wildcard) code() string {
+ builder := strings.Builder{}
+ for _, digit := range w {
+ _, _ = builder.WriteString(strconv.Itoa(digit))
+ }
+ _ = builder.WriteByte('*')
+ return builder.String()
+}
+
+type wildcardX []int
+
+// WildcardX creates a wildcard code with the given digits, and uses an 'x' instead of a '*' in the generated attribute.
+// For example, WildcardX(4, 1) results in hx-target-41x, and matches all 41x HTTP response codes.
+func WildcardX(digits ...int) wildcardX {
+ return digits
+}
+
+func (w wildcardX) code() string {
+ builder := strings.Builder{}
+ for _, digit := range w {
+ _, _ = builder.WriteString(strconv.Itoa(digit))
+ }
+ _ = builder.WriteByte('x')
+ return builder.String()
+}
+
+// Target specifies a target element to be swapped when specific HTTP response codes are received.
+//
+// Extension: [response-targets]
+//
+// [response-targets]: https://htmx.org/extensions/response-targets/
+func Target[T any](hx htmx.HX[T], code Code, extendedSelector htmx.TargetSelector) T {
+ attr := fmt.Sprintf("hx-target-%s", code.code())
+ return hx.Attr(htmx.Attribute(attr), string(extendedSelector))
+}
diff --git a/htmx/ext/responsetargets/responsetargets_test.go b/htmx/ext/responsetargets/responsetargets_test.go
new file mode 100644
index 0000000..cf19c01
--- /dev/null
+++ b/htmx/ext/responsetargets/responsetargets_test.go
@@ -0,0 +1,35 @@
+package responsetargets_test
+
+import (
+ "fmt"
+ "net/http"
+
+ "github.com/will-wow/typed-htmx-go/htmx"
+ "github.com/will-wow/typed-htmx-go/htmx/ext/responsetargets"
+)
+
+var hx = htmx.NewStringAttrs()
+
+func ExampleTarget_code() {
+ attr := responsetargets.Target(hx, responsetargets.Code(http.StatusNotFound), htmx.TargetRelative(htmx.Next, "div"))
+ fmt.Println(attr)
+ // Output: hx-target-404='next div'
+}
+
+func ExampleTarget_error() {
+ attr := responsetargets.Target(hx, responsetargets.Error, htmx.TargetThis)
+ fmt.Println(attr)
+ // Output: hx-target-error='this'
+}
+
+func ExampleTarget_wildcard() {
+ attr := responsetargets.Target(hx, responsetargets.Wildcard(4, 0), htmx.TargetRelative(htmx.Next, "div"))
+ fmt.Println(attr)
+ // Output: hx-target-40*='next div'
+}
+
+func ExampleTarget_wildcardX() {
+ attr := responsetargets.Target(hx, responsetargets.WildcardX(4, 0), htmx.TargetRelative(htmx.Next, "div"))
+ fmt.Println(attr)
+ // Output: hx-target-40x='next div'
+}
diff --git a/htmx/htmx.go b/htmx/htmx.go
index 9e7f642..084248a 100644
--- a/htmx/htmx.go
+++ b/htmx/htmx.go
@@ -796,6 +796,8 @@ func (hx *HX[T]) Encoding(encoding EncodingContentType) T {
return hx.attr(Encoding, string(encoding))
}
+// An Extension is the name of an htmx extension, to be passed to [HX.Ext()] to initialize the extension.
+// Extensions are in packages under htmx/ext.
type Extension string
// Ext enables an htmx [extension] for an element and all its children.