@zio.dev/zio-blocks 0.0.33 → 0.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/guides/compile-time-resource-safety-with-scope.md +16 -17
  2. package/guides/getting-started-with-mux.md +1507 -0
  3. package/guides/query-dsl-extending.md +161 -102
  4. package/guides/query-dsl-fluent-builder.md +217 -157
  5. package/guides/query-dsl-reified-optics.md +12 -10
  6. package/guides/query-dsl-sql.md +246 -165
  7. package/guides/telemetry-guide.md +1069 -0
  8. package/guides/zio-schema-migration.md +29 -22
  9. package/index.md +292 -50
  10. package/package.json +1 -1
  11. package/plans/config-follow-up-prs.md +188 -0
  12. package/plans/config-pr-assessment-roadmap.md +310 -0
  13. package/reference/MuxDataFlow.jsx +250 -0
  14. package/reference/async.md +651 -0
  15. package/reference/chunk.md +3533 -308
  16. package/reference/codegen/case-class.md +436 -0
  17. package/reference/codegen/emitter-config.md +383 -0
  18. package/reference/codegen/examples.md +664 -0
  19. package/reference/codegen/field.md +316 -0
  20. package/reference/codegen/index.md +317 -0
  21. package/reference/codegen/scala-emitter.md +392 -0
  22. package/reference/codegen/scala-file.md +276 -0
  23. package/reference/codegen/sealed-trait.md +408 -0
  24. package/reference/codegen/type-definition.md +340 -0
  25. package/reference/codegen/type-ref.md +201 -0
  26. package/reference/combinators.md +347 -117
  27. package/reference/config.md +158 -0
  28. package/reference/context.md +4 -4
  29. package/reference/datastar.md +346 -0
  30. package/reference/docs.md +1461 -345
  31. package/reference/endpoint/auth-type.md +146 -0
  32. package/reference/endpoint/endpoint.md +297 -0
  33. package/reference/endpoint/http-codec.md +249 -0
  34. package/reference/endpoint/index.md +825 -0
  35. package/reference/endpoint/path-codec.md +237 -0
  36. package/reference/endpoint/route-pattern.md +196 -0
  37. package/reference/endpoint/route-tree.md +111 -0
  38. package/reference/endpoint/segment-codec.md +212 -0
  39. package/reference/html.md +1120 -0
  40. package/reference/htmx/attribute-values.md +359 -0
  41. package/reference/htmx/hx-encoding.md +111 -0
  42. package/reference/htmx/hx-params.md +204 -0
  43. package/reference/htmx/hx-swap.md +276 -0
  44. package/reference/htmx/hx-sync.md +251 -0
  45. package/reference/htmx/hx-target.md +314 -0
  46. package/reference/htmx/hx-trigger.md +457 -0
  47. package/reference/htmx/hx-url-update.md +239 -0
  48. package/reference/htmx/index.md +855 -0
  49. package/reference/http-model/index.md +47 -0
  50. package/reference/http-model/model.md +1481 -0
  51. package/reference/http-model/schema.md +747 -0
  52. package/reference/maybe.md +826 -0
  53. package/reference/media-type.md +2 -2
  54. package/reference/mux.mdx +823 -0
  55. package/reference/openapi.md +1351 -0
  56. package/reference/resource-management/defer-handle.md +1 -1
  57. package/reference/resource-management/resource.md +31 -2
  58. package/reference/resource-management/scope.md +28 -12
  59. package/reference/resource-management/wire.md +3 -7
  60. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  61. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  62. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  63. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  64. package/reference/ringbuffer/advanced.mdx +109 -0
  65. package/reference/ringbuffer/index.mdx +145 -0
  66. package/reference/ringbuffer/mpmc.mdx +151 -0
  67. package/reference/ringbuffer/mpsc.mdx +132 -0
  68. package/reference/ringbuffer/spmc.mdx +108 -0
  69. package/reference/ringbuffer/spsc.mdx +344 -0
  70. package/reference/{allows.md → schema/allows.md} +4 -4
  71. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  72. package/reference/{binding.md → schema/binding.md} +2 -3
  73. package/reference/schema/built-in-codecs/avro.md +451 -0
  74. package/reference/schema/built-in-codecs/bson.md +480 -0
  75. package/reference/schema/built-in-codecs/csv.md +564 -0
  76. package/reference/schema/built-in-codecs/index.md +77 -0
  77. package/reference/schema/built-in-codecs/json/index.md +295 -0
  78. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  79. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
  80. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  81. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  82. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  83. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  84. package/reference/schema/built-in-codecs/thrift.md +433 -0
  85. package/reference/schema/built-in-codecs/toon.md +1078 -0
  86. package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
  87. package/reference/schema/built-in-codecs/yaml.md +552 -0
  88. package/reference/{codec.md → schema/codec.md} +10 -10
  89. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +151 -5
  90. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  91. package/reference/schema/format.md +92 -0
  92. package/reference/schema/index.md +50 -0
  93. package/reference/schema/migration.md +297 -0
  94. package/reference/{modifier.md → schema/modifier.md} +58 -7
  95. package/reference/{optics.md → schema/optics.md} +2 -2
  96. package/reference/{patch.md → schema/patch.md} +1 -1
  97. package/{path-interpolator.md → reference/schema/path-interpolator.md} +165 -72
  98. package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
  99. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  100. package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
  101. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  102. package/reference/{schema.md → schema/schema.md} +12 -0
  103. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  104. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  105. package/reference/smithy.md +533 -0
  106. package/reference/sql/db-codec-deriver.md +71 -0
  107. package/reference/sql/db-codec.md +687 -0
  108. package/reference/sql/db-con.md +271 -0
  109. package/reference/sql/db-connection.md +153 -0
  110. package/reference/sql/db-param-writer.md +77 -0
  111. package/reference/sql/db-param.md +66 -0
  112. package/reference/sql/db-result-reader.md +146 -0
  113. package/reference/sql/db-tx.md +82 -0
  114. package/reference/sql/db-value.md +41 -0
  115. package/reference/sql/ddl.md +85 -0
  116. package/reference/sql/frag.md +254 -0
  117. package/reference/sql/index.md +341 -0
  118. package/reference/sql/repo.md +600 -0
  119. package/reference/sql/sql-dialect.md +73 -0
  120. package/reference/sql/sql-logger.md +62 -0
  121. package/reference/sql/sql-name-mapper.md +70 -0
  122. package/reference/sql/table-metadata.md +134 -0
  123. package/reference/sql/table.md +448 -0
  124. package/reference/sql/transactor-zio.md +399 -0
  125. package/reference/sql/transactor.md +353 -0
  126. package/reference/sql-zio.md +112 -0
  127. package/reference/streams/concurrent-operators.md +106 -0
  128. package/reference/streams/index.md +653 -0
  129. package/reference/streams/pipeline.md +718 -0
  130. package/reference/streams/reader.md +1284 -0
  131. package/reference/streams/scala-2-compatibility.md +55 -0
  132. package/reference/streams/sink.md +1426 -0
  133. package/reference/streams/stream.md +2526 -0
  134. package/reference/streams/writer.md +1045 -0
  135. package/reference/streams/zero-boxing.md +275 -0
  136. package/reference/telemetry.md +693 -0
  137. package/reference/typeid.md +5 -19
  138. package/sidebars.js +238 -43
  139. package/reference/formats.md +0 -694
  140. package/reference/http-model.md +0 -1716
  141. package/reference/streams.md +0 -989
  142. package/ringbuffer.md +0 -249
  143. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  144. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  145. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  146. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  147. /package/reference/{registers.md → schema/registers.md} +0 -0
  148. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  149. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  150. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -0,0 +1,359 @@
1
+ ---
2
+ id: attribute-values
3
+ title: Attribute Values and Infrastructure
4
+ ---
5
+
6
+ This section documents supporting attribute value types and infrastructure for the HTMX DSL. These types handle specialized data encoding, configuration, and type-class infrastructure that enables extensibility.
7
+
8
+ ## Attribute Value Types
9
+
10
+ These types enable specialized data encoding and configuration:
11
+
12
+ ### HxVals — Custom Values
13
+
14
+ `HxVals` represents the `hx-vals` attribute, allowing you to send custom data alongside form parameters. It accepts both schema-backed values (automatically JSON-encoded) and raw JSON:
15
+
16
+ ```scala
17
+ import zio.http.htmx._
18
+ import zio.blocks.schema._
19
+ import zio.blocks.schema.json.Json
20
+
21
+ // From a schema-backed value
22
+ case class Extra(userId: Int, role: String)
23
+ HxVals.from(Extra(123, "admin"))
24
+
25
+ // From raw JSON
26
+ HxVals.json(Json.Object(Chunk("userId" -> Json.Number(123))))
27
+ ```
28
+
29
+ Use `HxVals.from[T](value)` with an implicit `Schema[T]` to automatically encode any data type to JSON. First, set up a schema for your data type:
30
+
31
+ ```scala
32
+ import zio.blocks.html._
33
+ import zio.http.htmx._
34
+ import zio.blocks.schema._
35
+
36
+ case class RequestContext(userId: Int, sessionId: String)
37
+ object RequestContext {
38
+ implicit val schema: Schema[RequestContext] = Schema.derived
39
+ }
40
+ ```
41
+
42
+ Then use it in your form:
43
+
44
+ ```scala
45
+ import zio.blocks.html._
46
+ import zio.http.htmx._
47
+
48
+ form(
49
+ hxPost := "/api/action",
50
+ hxVals := HxVals.from(RequestContext(42, "abc123")),
51
+ button("Submit")
52
+ )
53
+ ```
54
+
55
+ Or use `HxVals.json(json)` when you already have JSON. Set up the imports first:
56
+
57
+ ```scala
58
+ import zio.blocks.schema.json.Json
59
+ import zio.blocks.chunk.Chunk
60
+ ```
61
+
62
+ Then construct the JSON:
63
+
64
+ ```scala
65
+ import zio.blocks.html._
66
+ import zio.http.htmx._
67
+ import zio.blocks.schema.json.Json
68
+ import zio.blocks.chunk.Chunk
69
+
70
+ form(
71
+ hxPost := "/api/action",
72
+ hxVals := HxVals.json(Json.Object(Chunk("priority" -> Json.String("high")))),
73
+ button("Submit")
74
+ )
75
+ ```
76
+
77
+ ### HxHeadersValue — Custom Headers
78
+
79
+ `HxHeadersValue` represents the `hx-headers` attribute, sending custom HTTP headers with HTMX requests. Like `HxVals`, it accepts schema-backed values or raw JSON:
80
+
81
+ ```scala
82
+ import zio.http.htmx._
83
+ import zio.blocks.schema.json.Json
84
+ import zio.blocks.chunk.Chunk
85
+
86
+ // From raw JSON object
87
+ val example1 = HxHeadersValue.json(Json.Object(Chunk(
88
+ "X-Custom-Header" -> Json.String("value"),
89
+ "X-Request-ID" -> Json.String("12345")
90
+ )))
91
+
92
+ // From a schema-backed value
93
+ import zio.blocks.schema._
94
+ case class Headers(traceId: String)
95
+ object Headers {
96
+ implicit val schema: Schema[Headers] = Schema.derived
97
+ }
98
+ val example2 = HxHeadersValue.from(Headers("xyz789"))
99
+ ```
100
+
101
+ Add custom headers to all requests within an element:
102
+
103
+ ```scala
104
+ import zio.blocks.html._
105
+ import zio.http.htmx._
106
+ import zio.blocks.schema.json.Json
107
+ import zio.blocks.chunk.Chunk
108
+
109
+ div(
110
+ hxHeaders := HxHeadersValue.json(Json.Object(Chunk(
111
+ "X-API-Key" -> Json.String("secret123"),
112
+ "X-Client-Version" -> Json.String("2.0")
113
+ ))),
114
+ button(hxPost := "/action", "Request (with custom headers)")
115
+ )
116
+ ```
117
+
118
+ ### HxSwapOob — Out-of-Bounds Swaps
119
+
120
+ `HxSwapOob` represents the `hx-swap-oob` attribute, enabling out-of-bounds swaps that update content outside the primary request target. This allows a single response to update multiple DOM regions simultaneously.
121
+
122
+ Use `HxSwapOob(true)` or `HxSwapOob(false)` for boolean flags:
123
+
124
+ ```scala
125
+ import zio.blocks.html._
126
+ import zio.http.htmx._
127
+
128
+ div(
129
+ id := "status-badge",
130
+ hxSwapOob := HxSwapOob(true),
131
+ "Ready"
132
+ )
133
+ ```
134
+
135
+ Or use `HxSwapOob.using(swap)` to specify a swap strategy:
136
+
137
+ ```scala
138
+ import zio.blocks.html._
139
+ import zio.http.htmx._
140
+
141
+ div(
142
+ id := "notification",
143
+ hxSwapOob := HxSwapOob.using(HxSwap.BeforeEnd),
144
+ span("New notification")
145
+ )
146
+ ```
147
+
148
+ Combine with a target selector:
149
+
150
+ ```scala
151
+ import zio.blocks.html._
152
+ import zio.http.htmx._
153
+
154
+ div(
155
+ hxSwapOob := HxSwapOob.using(
156
+ HxSwap.InnerHTML,
157
+ HxTarget.css("#status")
158
+ ),
159
+ "Updated Status"
160
+ )
161
+ ```
162
+
163
+ ### HxExtensions — HTMX Extensions
164
+
165
+ `HxExtensions` represents the `hx-ext` attribute, enabling HTMX extensions. Pass extension names as comma-separated values:
166
+
167
+ ```scala
168
+ import zio.http.htmx._
169
+
170
+ // Enable multiple extensions
171
+ HxExtensions("json-enc", "class-tools")
172
+ ```
173
+
174
+ Use in elements to opt in to extensions:
175
+
176
+ ```scala
177
+ import zio.blocks.html._
178
+ import zio.http.htmx._
179
+
180
+ form(
181
+ hxPost := "/api/submit",
182
+ hxExt := HxExtensions("json-enc", "debug"),
183
+ button("Submit")
184
+ )
185
+ ```
186
+
187
+ The `hxExt` attribute key provides a convenience builder to construct extensions:
188
+
189
+ ```scala
190
+ import zio.blocks.html._
191
+ import zio.http.htmx._
192
+
193
+ form(
194
+ hxExt("json-enc", "class-tools"),
195
+ button("Submit")
196
+ )
197
+ ```
198
+
199
+ ### HxAttributeNames — Attribute Disinheritance
200
+
201
+ `HxAttributeNames` represents the `hx-disinherit` attribute, preventing child elements from inheriting specific HTMX attributes from their ancestors. Pass attribute names as space-separated values:
202
+
203
+ ```scala
204
+ import zio.http.htmx._
205
+
206
+ // Prevent inheriting these attributes
207
+ HxAttributeNames("hx-trigger", "hx-swap")
208
+ ```
209
+
210
+ Use to override inherited attributes:
211
+
212
+ ```scala
213
+ import zio.blocks.html._
214
+ import zio.http.htmx._
215
+
216
+ div(
217
+ hxPost := "/parent-action",
218
+ hxTrigger := HxTrigger.click,
219
+ button(
220
+ hxDisinherit := HxAttributeNames("hx-post", "hx-trigger"),
221
+ hxPost := "/child-action",
222
+ hxTrigger := HxTrigger.submit,
223
+ "Child (overrides parent)"
224
+ )
225
+ )
226
+ ```
227
+
228
+ The `hxDisinherit` attribute key provides a convenience builder:
229
+
230
+ ```scala
231
+ import zio.blocks.html._
232
+ import zio.http.htmx._
233
+
234
+ div(
235
+ hxPost := "/parent-action",
236
+ button(
237
+ hxDisinherit("hx-post", "hx-trigger"),
238
+ hxPost := "/child-action",
239
+ "Child"
240
+ )
241
+ )
242
+ ```
243
+
244
+ ## Infrastructure Types
245
+
246
+ These types provide the internal machinery for the HTMX DSL:
247
+
248
+ ### HtmxAttrKey — Typed Attribute Keys
249
+
250
+ `HtmxAttrKey[-A]` is the typed attribute key binding an attribute name to its expected value type. Unlike plain HTML attributes, HTMX attributes carry compile-time type information, preventing type mismatches.
251
+
252
+ The `HtmxAttributes` mixin provides predefined keys like `hxPost`, `hxSwap`, `hxTarget`, etc.; use these rather than constructing `HtmxAttrKey` directly. Each key enforces the correct value type:
253
+
254
+ ```scala
255
+ import zio.blocks.html._
256
+ import zio.http.htmx._
257
+
258
+ // hxSwap expects HxSwap; this compiles
259
+ div(hxSwap := HxSwap.InnerHTML)
260
+
261
+ // hxTarget expects HxTarget; this compiles
262
+ div(hxTarget := HxTarget.This)
263
+
264
+ // hxPost expects UrlLike (String | Path | URL); this compiles
265
+ div(hxPost := "/api/endpoint")
266
+ ```
267
+
268
+ ### ToHtmxValue — Type Class for Rendering
269
+
270
+ `ToHtmxValue[-A]` is the type class that renders HTMX domain values to attribute strings. It's automatically derived for types like `HxSwap`, `HxTarget`, `HxTrigger`, and basic primitives.
271
+
272
+ The module provides instances for common types out of the box:
273
+
274
+ - **Primitives:** `String`, `Boolean`, `Int`, `Long`, `Double` render to their string representations
275
+ - **Selectors:** `CssSelector` renders via its `render` method
276
+ - **URLs:** `Path` and `URL` render to encoded strings
277
+ - **HTMX domain types:** `HxSwap`, `HxTarget`, `HxTrigger`, `HxParams`, etc. render via their `render` methods
278
+ - **Schema-backed types:** `Schema[A]` instances enable `HxVals.from()` to encode any data to JSON
279
+
280
+ #### Extending with Custom Types
281
+
282
+ Define your own `ToHtmxValue` instance to make custom domain types work in the HTMX DSL:
283
+
284
+ ```scala
285
+ import zio.http.htmx._
286
+
287
+ sealed trait Priority
288
+ object Priority {
289
+ case object Low extends Priority
290
+ case object Medium extends Priority
291
+ case object High extends Priority
292
+
293
+ implicit val toHtmxValue: ToHtmxValue[Priority] = new ToHtmxValue[Priority] {
294
+ def toHtmxValue(value: Priority): String = value match {
295
+ case Low => "low"
296
+ case Medium => "medium"
297
+ case High => "high"
298
+ }
299
+ }
300
+ }
301
+ ```
302
+
303
+ Use `Priority` values directly in HTMX attributes through the `ToHtmxValue` type class:
304
+
305
+ ```scala
306
+ import zio.blocks.html._
307
+ import zio.http.htmx._
308
+
309
+ button(
310
+ hxPost := "/api/task",
311
+ hxOn.click := Js(s"console.log('Priority: ${Priority.High.toString()}')"),
312
+ "Create High Priority Task"
313
+ )
314
+ ```
315
+
316
+ #### Implicit Resolution
317
+
318
+ When you assign a value to an HTMX attribute, the type class is summoned implicitly:
319
+
320
+ ```scala
321
+ import zio.blocks.html._
322
+ import zio.http.htmx._
323
+
324
+ // Implicit ToHtmxValue[HxSwap] is summoned
325
+ div(hxSwap := HxSwap.InnerHTML)
326
+
327
+ // Implicit ToHtmxValue[String] is summoned
328
+ div(hxPost := "/endpoint")
329
+ ```
330
+
331
+ If you get an error like "No `ToHtmxValue` instance found for type X," implement the type class for your custom type as shown above.
332
+
333
+ ## Integration
334
+
335
+ These types work together to provide a complete, extensible HTMX DSL. For example, a form might use multiple attribute value types:
336
+
337
+ ```scala
338
+ import zio.blocks.html._
339
+ import zio.http.htmx._
340
+ import zio.blocks.schema.json.Json
341
+ import zio.blocks.chunk.Chunk
342
+ import scala.concurrent.duration._
343
+
344
+ form(
345
+ hxPost := "/api/submit",
346
+ hxTrigger := HxTrigger.submit,
347
+ hxTarget := HxTarget.closest("form"),
348
+ hxSwap := HxSwap.InnerHTML.settle(250.millis),
349
+ hxParams := HxParams.only("name", "email"),
350
+ hxEncoding := HxEncoding.Multipart,
351
+ hxHeaders := HxHeadersValue.json(Json.Object(Chunk(
352
+ "X-Request-ID" -> Json.String("12345")
353
+ ))),
354
+ hxVals := HxVals.from(RequestContext(42, "session-abc")),
355
+ button("Submit")
356
+ )
357
+ ```
358
+
359
+ Each attribute key is type-safe, and the `ToHtmxValue` type class ensures values render correctly to HTMX syntax.
@@ -0,0 +1,111 @@
1
+ ---
2
+ id: hx-encoding
3
+ title: HxEncoding
4
+ ---
5
+
6
+ `HxEncoding` represents the `hx-encoding` attribute, controlling how form data is encoded when sent in an HTMX request. The primary use case is file uploads, which require `multipart/form-data` encoding instead of the default URL-encoded form submission.
7
+
8
+ Use `HxEncoding.Multipart` to enable multipart form data encoding for requests that include file fields. Here is the core pattern:
9
+
10
+ ```scala
11
+ import zio.http.htmx._
12
+
13
+ // Multipart encoding (for file uploads)
14
+ HxEncoding.Multipart
15
+ ```
16
+
17
+ ## Encoding Strategies
18
+
19
+ **`HxEncoding.Multipart`** sets the `hx-encoding` attribute to `multipart/form-data`, enabling file uploads and other multipart data:
20
+
21
+ ```scala
22
+ import zio.blocks.html._
23
+ import zio.http.htmx._
24
+
25
+ form(
26
+ hxPost := "/upload",
27
+ hxEncoding := HxEncoding.Multipart,
28
+ input(name := "file", `type` := "file"),
29
+ input(name := "description"),
30
+ button("Upload")
31
+ )
32
+ ```
33
+
34
+ When you omit `hxEncoding`, HTMX uses the default encoding (URL-encoded form data), so there is no DSL value for the default case. This keeps the DSL focused on the special cases that deviate from the default.
35
+
36
+ ## Common Patterns
37
+
38
+ Multipart encoding enables file uploads in HTMX forms. Here are practical usage patterns:
39
+
40
+ ### File Upload with Metadata
41
+
42
+ Send a file along with additional form fields:
43
+
44
+ ```scala
45
+ import zio.blocks.html._
46
+ import zio.http.htmx._
47
+
48
+ form(
49
+ hxPost := "/api/upload-document",
50
+ hxEncoding := HxEncoding.Multipart,
51
+ hxTarget := HxTarget.css("#upload-status"),
52
+ hxSwap := HxSwap.InnerHTML,
53
+ fieldset(
54
+ legend("Upload Document"),
55
+ input(
56
+ name := "file",
57
+ `type` := "file",
58
+ accept := ".pdf,.doc,.docx"
59
+ ),
60
+ input(
61
+ name := "title",
62
+ placeholder := "Document Title"
63
+ ),
64
+ textarea(name := "description", "Description"),
65
+ button("Upload")
66
+ )
67
+ )
68
+ ```
69
+
70
+ ### Profile Picture Upload
71
+
72
+ Update a profile picture with multipart encoding:
73
+
74
+ ```scala
75
+ import zio.blocks.html._
76
+ import zio.http.htmx._
77
+
78
+ form(
79
+ hxPost := "/api/profile-picture",
80
+ hxEncoding := HxEncoding.Multipart,
81
+ hxTarget := HxTarget.css("#profile-pic"),
82
+ hxSwap := HxSwap.OuterHTML,
83
+ input(
84
+ name := "image",
85
+ `type` := "file",
86
+ accept := "image/*"
87
+ ),
88
+ button("Update Picture")
89
+ )
90
+ ```
91
+
92
+ ## Integration with Other Request Control Attributes
93
+
94
+ `HxEncoding` works alongside `HxParams` to control both how data is encoded and which fields are sent:
95
+
96
+ ```scala
97
+ import zio.blocks.html._
98
+ import zio.http.htmx._
99
+
100
+ form(
101
+ hxPost := "/upload",
102
+ hxEncoding := HxEncoding.Multipart,
103
+ hxParams := HxParams.only("file", "title"), // only send these fields
104
+ input(name := "file", `type` := "file"),
105
+ input(name := "title"),
106
+ input(name := "csrf_token"), // excluded by hxParams
107
+ button("Upload")
108
+ )
109
+ ```
110
+
111
+ The `ToHtmxValue[HxEncoding]` instance renders automatically, so `HxEncoding` values work seamlessly with the `hxEncoding` attribute key.
@@ -0,0 +1,204 @@
1
+ ---
2
+ id: hx-params
3
+ title: HxParams
4
+ ---
5
+
6
+ `HxParams` represents the `hx-params` attribute, controlling which form parameters are included in the HTMX request. Instead of sending all form fields, you can explicitly allow or forbid specific parameters through compile-safe domain types.
7
+
8
+ Use `HxParams.All` to include all parameters, `HxParams.None` to include none, or `HxParams.only()` and `HxParams.not()` to allow/forbid specific names. Here are the core patterns:
9
+
10
+ ```scala
11
+ import zio.http.htmx._
12
+
13
+ // Include all parameters
14
+ HxParams.All
15
+
16
+ // Include no parameters
17
+ HxParams.None
18
+
19
+ // Include only specific parameters
20
+ HxParams.only("query", "page")
21
+
22
+ // Exclude specific parameters
23
+ HxParams.not("csrf_token", "session")
24
+ ```
25
+
26
+ ## Strategies
27
+
28
+ **`HxParams.All`** includes all form parameters in the request (the default HTMX behavior):
29
+
30
+ ```scala
31
+ import zio.blocks.html._
32
+ import zio.http.htmx._
33
+
34
+ input(
35
+ hxPost := "/search",
36
+ hxParams := HxParams.All
37
+ )
38
+ ```
39
+
40
+ **`HxParams.None`** excludes all form parameters. The request body is empty:
41
+
42
+ ```scala
43
+ import zio.blocks.html._
44
+ import zio.http.htmx._
45
+
46
+ button(
47
+ hxPost := "/ping",
48
+ hxParams := HxParams.None,
49
+ "Ping Server"
50
+ )
51
+ ```
52
+
53
+ **`HxParams.only(first, rest*)`** includes only the listed parameters by name:
54
+
55
+ ```scala
56
+ import zio.blocks.html._
57
+ import zio.http.htmx._
58
+
59
+ input(
60
+ hxPost := "/search",
61
+ hxParams := HxParams.only("query", "page", "limit"),
62
+ placeholder := "Search..."
63
+ )
64
+ ```
65
+
66
+ **`HxParams.not(first, rest*)`** excludes the listed parameters, sending all others:
67
+
68
+ ```scala
69
+ import zio.blocks.html._
70
+ import zio.http.htmx._
71
+
72
+ form(
73
+ hxPost := "/submit",
74
+ hxParams := HxParams.not("csrf_token", "_method"),
75
+ input(name := "username"),
76
+ input(name := "csrf_token"),
77
+ button("Submit")
78
+ )
79
+ ```
80
+
81
+ ## Rendering & Parsing
82
+
83
+ **`render: String`** produces the literal `hx-params` attribute value string:
84
+
85
+ ```scala
86
+ import zio.http.htmx._
87
+
88
+ HxParams.All.render // "*"
89
+ HxParams.None.render // "none"
90
+ HxParams.only("query", "page").render // "query,page"
91
+ HxParams.not("csrf_token", "session").render // "not csrf_token,session"
92
+ ```
93
+
94
+ **`HxParams.parse(value: String): Either[String, HxParams]`** parses a rendered string back into a typed `HxParams`:
95
+
96
+ ```scala
97
+ import zio.http.htmx._
98
+
99
+ HxParams.parse("*") // Right(HxParams.All)
100
+ HxParams.parse("none") // Right(HxParams.None)
101
+ HxParams.parse("query,page") // Right(HxParams.only("query", "page"))
102
+ HxParams.parse("not csrf,session") // Right(HxParams.not("csrf", "session"))
103
+ ```
104
+
105
+ Parse failures return a descriptive `Left`:
106
+
107
+ ```scala
108
+ import zio.http.htmx._
109
+
110
+ HxParams.parse("") // Left("HTMX params list must be non-empty")
111
+ HxParams.parse("query,,page") // Left("HTMX params list cannot contain empty names")
112
+ ```
113
+
114
+ ## Common Patterns
115
+
116
+ `HxParams` is useful when you need fine-grained control over which form fields are sent to the server. Here are representative usage patterns:
117
+
118
+ ### Search Without CSRF Token
119
+
120
+ Include only the search query parameter, excluding the CSRF token typically added by form handlers:
121
+
122
+ ```scala
123
+ import zio.blocks.html._
124
+ import zio.http.htmx._
125
+
126
+ input(
127
+ name := "query",
128
+ hxPost := "/search",
129
+ hxParams := HxParams.only("query"),
130
+ placeholder := "Search..."
131
+ )
132
+ ```
133
+
134
+ ### Selective Parameter Submission
135
+
136
+ When a form has many fields but an HTMX request should only send a few:
137
+
138
+ ```scala
139
+ import zio.blocks.html._
140
+ import zio.http.htmx._
141
+
142
+ form(
143
+ input(name := "firstName"),
144
+ input(name := "lastName"),
145
+ input(
146
+ name := "email",
147
+ hxPost := "/validate-email",
148
+ hxParams := HxParams.only("email"),
149
+ hxTarget := HxTarget.next(".error"),
150
+ placeholder := "Email"
151
+ ),
152
+ div("Error message")
153
+ )
154
+ ```
155
+
156
+ ### Exclude Framework Parameters
157
+
158
+ Prevent sending framework-specific parameters (like Rails' `_method`, CSRF tokens) to the HTMX endpoint:
159
+
160
+ ```scala
161
+ import zio.blocks.html._
162
+ import zio.http.htmx._
163
+
164
+ form(
165
+ hxPost := "/api/submit",
166
+ hxParams := HxParams.not("_method", "authenticity_token", "utf8"),
167
+ button("Submit")
168
+ )
169
+ ```
170
+
171
+ ### No Parameter Request
172
+
173
+ Send a request without any form data, useful for server-side-only actions:
174
+
175
+ ```scala
176
+ import zio.blocks.html._
177
+ import zio.http.htmx._
178
+
179
+ button(
180
+ hxPost := "/logout",
181
+ hxParams := HxParams.None,
182
+ "Logout"
183
+ )
184
+ ```
185
+
186
+ ## Integration with Request Control
187
+
188
+ `HxParams` works with other request-control attributes like `hxEncoding` and `hxSync`:
189
+
190
+ ```scala
191
+ import zio.blocks.html._
192
+ import zio.http.htmx._
193
+
194
+ form(
195
+ hxPost := "/upload",
196
+ hxParams := HxParams.only("file", "description"),
197
+ hxEncoding := HxEncoding.Multipart,
198
+ input(name := "file", `type` := "file"),
199
+ input(name := "description"),
200
+ button("Upload")
201
+ )
202
+ ```
203
+
204
+ The `ToHtmxValue[HxParams]` instance renders automatically, so `HxParams` values work seamlessly with the `hxParams` attribute key.