@zio.dev/zio-blocks 0.0.33 → 0.0.55

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 (215) hide show
  1. package/adr/2026-07-18-data-migration.md +123 -0
  2. package/guides/async-getting-started.md +687 -0
  3. package/guides/compile-time-resource-safety-with-scope.md +21 -16
  4. package/guides/getting-started-with-mux.md +1395 -0
  5. package/guides/query-dsl-extending.md +161 -102
  6. package/guides/query-dsl-fluent-builder.md +217 -157
  7. package/guides/query-dsl-reified-optics.md +12 -10
  8. package/guides/query-dsl-sql.md +640 -165
  9. package/guides/sql-checked-interpolation.md +173 -0
  10. package/guides/sql-transactions.md +286 -0
  11. package/guides/telemetry-guide.md +1130 -0
  12. package/guides/zio-schema-migration.md +29 -22
  13. package/index.md +248 -389
  14. package/package.json +1 -1
  15. package/plans/config-follow-up-prs.md +188 -0
  16. package/plans/config-pr-assessment-roadmap.md +310 -0
  17. package/reference/MuxDataFlow.jsx +250 -0
  18. package/reference/async.md +1499 -0
  19. package/reference/chunk.md +3533 -308
  20. package/reference/codegen/case-class.md +436 -0
  21. package/reference/codegen/emitter-config.md +383 -0
  22. package/reference/codegen/examples.md +664 -0
  23. package/reference/codegen/field.md +316 -0
  24. package/reference/codegen/index.md +317 -0
  25. package/reference/codegen/scala-emitter.md +392 -0
  26. package/reference/codegen/scala-file.md +276 -0
  27. package/reference/codegen/sealed-trait.md +408 -0
  28. package/reference/codegen/type-definition.md +340 -0
  29. package/reference/codegen/type-ref.md +201 -0
  30. package/reference/combinators.md +347 -117
  31. package/reference/config/config-decoder.md +460 -0
  32. package/reference/config/config-source.md +489 -0
  33. package/reference/config/errors.md +278 -0
  34. package/reference/config/flags.md +369 -0
  35. package/reference/config/formats.md +314 -0
  36. package/reference/config/index.md +304 -0
  37. package/reference/config/rollout.md +336 -0
  38. package/reference/context.md +9 -52
  39. package/reference/data-migration.md +269 -0
  40. package/reference/datastar/attributes.md +302 -0
  41. package/reference/datastar/events.md +234 -0
  42. package/reference/datastar/index.md +256 -0
  43. package/reference/datastar/signals.md +230 -0
  44. package/reference/datastar/sse.md +295 -0
  45. package/reference/datastar.md +346 -0
  46. package/reference/docs.md +1461 -345
  47. package/reference/endpoint/auth-type.md +146 -0
  48. package/reference/endpoint/bulk-creation.md +96 -0
  49. package/reference/endpoint/endpoint.md +297 -0
  50. package/reference/endpoint/http-codec.md +249 -0
  51. package/reference/endpoint/index.md +745 -0
  52. package/reference/endpoint/path-codec.md +225 -0
  53. package/reference/endpoint/route-pattern.md +194 -0
  54. package/reference/endpoint/route-tree.md +111 -0
  55. package/reference/endpoint/segment-codec.md +199 -0
  56. package/reference/html.md +1424 -0
  57. package/reference/htmx/attribute-values.md +359 -0
  58. package/reference/htmx/hx-encoding.md +111 -0
  59. package/reference/htmx/hx-params.md +204 -0
  60. package/reference/htmx/hx-swap.md +276 -0
  61. package/reference/htmx/hx-sync.md +251 -0
  62. package/reference/htmx/hx-target.md +314 -0
  63. package/reference/htmx/hx-trigger.md +457 -0
  64. package/reference/htmx/hx-url-update.md +239 -0
  65. package/reference/htmx/index.md +807 -0
  66. package/reference/htmx/response-headers.md +240 -0
  67. package/reference/http-model/headers.md +735 -0
  68. package/reference/http-model/index.md +49 -0
  69. package/reference/http-model/model.md +1517 -0
  70. package/reference/http-model/schema-codecs.md +522 -0
  71. package/reference/http-model/schema.md +750 -0
  72. package/reference/http-model/server-sent-event.md +341 -0
  73. package/reference/jwt.md +195 -0
  74. package/reference/maybe.md +943 -0
  75. package/reference/media-type.md +2 -2
  76. package/reference/mux.md +254 -0
  77. package/reference/mux.mdx +828 -0
  78. package/reference/openapi.md +1351 -0
  79. package/reference/projection.md +654 -0
  80. package/reference/resource-management/defer-handle.md +1 -1
  81. package/reference/resource-management/resource.md +31 -98
  82. package/reference/resource-management/scope.md +28 -220
  83. package/reference/resource-management/wire.md +5 -55
  84. package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
  85. package/reference/ringbuffer/MpscDiagram.jsx +618 -0
  86. package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
  87. package/reference/ringbuffer/SpscDiagram.jsx +677 -0
  88. package/reference/ringbuffer/advanced.mdx +109 -0
  89. package/reference/ringbuffer/index.mdx +145 -0
  90. package/reference/ringbuffer/mpmc.mdx +185 -0
  91. package/reference/ringbuffer/mpsc.mdx +164 -0
  92. package/reference/ringbuffer/spmc.mdx +108 -0
  93. package/reference/ringbuffer/spsc.mdx +416 -0
  94. package/reference/{allows.md → schema/allows.md} +4 -100
  95. package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
  96. package/reference/{binding.md → schema/binding.md} +3 -4
  97. package/reference/schema/built-in-codecs/avro.md +451 -0
  98. package/reference/schema/built-in-codecs/bson.md +510 -0
  99. package/reference/schema/built-in-codecs/csv.md +564 -0
  100. package/reference/schema/built-in-codecs/index.md +77 -0
  101. package/reference/schema/built-in-codecs/json/index.md +295 -0
  102. package/reference/schema/built-in-codecs/json/json-config.md +217 -0
  103. package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
  104. package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
  105. package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
  106. package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
  107. package/reference/schema/built-in-codecs/messagepack.md +508 -0
  108. package/reference/schema/built-in-codecs/thrift.md +433 -0
  109. package/reference/schema/built-in-codecs/toon.md +1078 -0
  110. package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
  111. package/reference/schema/built-in-codecs/yaml.md +552 -0
  112. package/reference/{codec.md → schema/codec.md} +11 -11
  113. package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
  114. package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
  115. package/reference/schema/format.md +92 -0
  116. package/reference/schema/index.md +52 -0
  117. package/reference/schema/migration.md +297 -0
  118. package/reference/{modifier.md → schema/modifier.md} +58 -7
  119. package/reference/{optics.md → schema/optics.md} +2 -2
  120. package/reference/{patch.md → schema/patch.md} +1 -1
  121. package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
  122. package/reference/schema/reflect-transformer.md +140 -0
  123. package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
  124. package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
  125. package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
  126. package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
  127. package/reference/schema/schema-search.md +263 -0
  128. package/reference/{schema.md → schema/schema.md} +22 -2
  129. package/reference/{structural-types.md → schema/structural-types.md} +1 -1
  130. package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
  131. package/reference/smithy.md +1032 -0
  132. package/reference/sql/db-codec-deriver.md +71 -0
  133. package/reference/sql/db-codec.md +687 -0
  134. package/reference/sql/db-con.md +271 -0
  135. package/reference/sql/db-connection.md +153 -0
  136. package/reference/sql/db-param-writer.md +77 -0
  137. package/reference/sql/db-param.md +66 -0
  138. package/reference/sql/db-result-reader.md +148 -0
  139. package/reference/sql/db-tx.md +114 -0
  140. package/reference/sql/db-value.md +41 -0
  141. package/reference/sql/ddl.md +85 -0
  142. package/reference/sql/frag.md +288 -0
  143. package/reference/sql/index.md +341 -0
  144. package/reference/sql/repo.md +600 -0
  145. package/reference/sql/sql-dialect.md +73 -0
  146. package/reference/sql/sql-logger.md +62 -0
  147. package/reference/sql/sql-name-mapper.md +70 -0
  148. package/reference/sql/table-metadata.md +134 -0
  149. package/reference/sql/table.md +448 -0
  150. package/reference/sql/transactor-zio.md +399 -0
  151. package/reference/sql/transactor.md +363 -0
  152. package/reference/sql-zio.md +112 -0
  153. package/reference/streams/core/index.md +32 -0
  154. package/reference/streams/core/pipeline.md +854 -0
  155. package/reference/streams/core/sink.md +1404 -0
  156. package/reference/streams/core/stream.md +3236 -0
  157. package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
  158. package/reference/streams/execution-and-compatibility/index.md +35 -0
  159. package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
  160. package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
  161. package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
  162. package/reference/streams/index.md +726 -0
  163. package/reference/streams/primitives/index.md +30 -0
  164. package/reference/streams/primitives/reader.md +1992 -0
  165. package/reference/streams/primitives/writer.md +1201 -0
  166. package/reference/telemetry/common/any-value.md +90 -0
  167. package/reference/telemetry/common/attribute-key.md +87 -0
  168. package/reference/telemetry/common/attributes.md +118 -0
  169. package/reference/telemetry/common/index.md +39 -0
  170. package/reference/telemetry/common/instrumentation-scope.md +24 -0
  171. package/reference/telemetry/common/resource.md +34 -0
  172. package/reference/telemetry/index.md +311 -0
  173. package/reference/telemetry/logging/index.md +197 -0
  174. package/reference/telemetry/logging/log-enrichment.md +72 -0
  175. package/reference/telemetry/logging/log-formatter.md +100 -0
  176. package/reference/telemetry/logging/log-record-processor.md +56 -0
  177. package/reference/telemetry/logging/log-record.md +44 -0
  178. package/reference/telemetry/logging/log-writer.md +64 -0
  179. package/reference/telemetry/logging/logger-provider.md +142 -0
  180. package/reference/telemetry/logging/logger.md +83 -0
  181. package/reference/telemetry/logging/severity.md +62 -0
  182. package/reference/telemetry/metrics/index.md +150 -0
  183. package/reference/telemetry/metrics/instruments.md +183 -0
  184. package/reference/telemetry/metrics/labeled-instruments.md +74 -0
  185. package/reference/telemetry/metrics/meter-provider.md +76 -0
  186. package/reference/telemetry/metrics/meter.md +98 -0
  187. package/reference/telemetry/metrics/metric-data.md +57 -0
  188. package/reference/telemetry/otel/custom-exporter.md +216 -0
  189. package/reference/telemetry/otel/index.md +212 -0
  190. package/reference/telemetry/tracing/index.md +155 -0
  191. package/reference/telemetry/tracing/sampler.md +89 -0
  192. package/reference/telemetry/tracing/span-builder.md +57 -0
  193. package/reference/telemetry/tracing/span-context.md +39 -0
  194. package/reference/telemetry/tracing/span-data.md +32 -0
  195. package/reference/telemetry/tracing/span-kind.md +55 -0
  196. package/reference/telemetry/tracing/span-processor.md +53 -0
  197. package/reference/telemetry/tracing/span-status.md +47 -0
  198. package/reference/telemetry/tracing/span.md +117 -0
  199. package/reference/telemetry/tracing/tracer-provider.md +91 -0
  200. package/reference/telemetry/tracing/tracer.md +52 -0
  201. package/reference/typeid.md +5 -83
  202. package/sidebars.js +376 -43
  203. package/undocumented-report.md +528 -270
  204. package/reference/formats.md +0 -694
  205. package/reference/http-model.md +0 -1716
  206. package/reference/streams.md +0 -989
  207. package/ringbuffer.md +0 -249
  208. /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
  209. /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
  210. /package/reference/{lazy.md → schema/lazy.md} +0 -0
  211. /package/reference/{reflect.md → schema/reflect.md} +0 -0
  212. /package/reference/{registers.md → schema/registers.md} +0 -0
  213. /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
  214. /package/reference/{syntax.md → schema/syntax.md} +0 -0
  215. /package/reference/{validation.md → schema/validation.md} +0 -0
@@ -0,0 +1,346 @@
1
+ ---
2
+ id: datastar
3
+ title: "Datastar"
4
+ ---
5
+
6
+ `zio-blocks-datastar` provides a type-safe Scala SDK for [Datastar](https://data-star.dev/), the hypermedia framework that brings reactive UIs via server-sent events (SSE). It builds on `zio-blocks-html` for DOM construction and `zio-blocks-schema` for JSON serialization.
7
+
8
+ ## Installation
9
+
10
+ ```scala
11
+ // JVM
12
+ libraryDependencies += "dev.zio" %% "zio-blocks-datastar" % "0.0.55"
13
+
14
+ // Scala.js
15
+ libraryDependencies += "dev.zio" %%% "zio-blocks-datastar" % "0.0.55"
16
+ ```
17
+
18
+ ## Signals
19
+
20
+ A `Signal[A]` represents a named reactive signal on the client. Use `:=` to pair it with a value, producing a `SignalUpdate` ready for SSE transmission:
21
+
22
+ ```scala
23
+ import zio.http.datastar._
24
+ import zio.blocks.schema.Schema
25
+
26
+ case class User(name: String, age: Int)
27
+ object User {
28
+ implicit val schema: Schema[User] = Schema.derived
29
+ }
30
+
31
+ val count = Signal[Int]("count")
32
+ val username = Signal[String]("username")
33
+
34
+ // Create signal updates (serializes via Schema's cached JSON codec)
35
+ val update1 = count := 0
36
+ val update2 = username := "Alice"
37
+ ```
38
+
39
+ ## SSE Events
40
+
41
+ `DatastarEvent` is the sealed trait representing events sent to the browser. Use the companion object's builder methods:
42
+
43
+ ### patchSignals
44
+
45
+ Send signal updates to the client:
46
+
47
+ ```scala
48
+ val sse = DatastarEvent
49
+ .patchSignals(count := 42, username := "Bob")
50
+ .renderSSE
51
+
52
+ // With options:
53
+ val sseWithOptions = DatastarEvent
54
+ .patchSignals(count := 1)
55
+ .withOnlyIfMissing
56
+ .withEventId("evt-1")
57
+ .withRetry(5000)
58
+ .renderSSE
59
+ ```
60
+
61
+ ### patchElements
62
+
63
+ Send DOM fragments to the client:
64
+
65
+ ```scala
66
+ import zio.blocks.html._
67
+
68
+ val sse = DatastarEvent
69
+ .patchElements(div(id := "status")("Online"))
70
+ .withSelector(CssSelector.id("status"))
71
+ .withMode(ElementPatchMode.Inner)
72
+ .withViewTransition
73
+ .renderSSE
74
+ ```
75
+
76
+ ### executeScript
77
+
78
+ Run JavaScript on the client:
79
+
80
+ ```scala
81
+ val sse = DatastarEvent
82
+ .executeScript(js"console.log('hello')")
83
+ .renderSSE
84
+ ```
85
+
86
+ ### removeElements
87
+
88
+ Remove elements matching a CSS selector:
89
+
90
+ ```scala
91
+ val sse = DatastarEvent
92
+ .removeElements(CssSelector.id("old-item"))
93
+ .renderSSE
94
+ ```
95
+
96
+ ## Attribute DSL
97
+
98
+ Import `zio.http.datastar._` to get all `data-*` attribute constructors. These integrate with the `zio-blocks-html` DSL:
99
+
100
+ ```scala
101
+ import zio.blocks.html._
102
+ import zio.http.datastar._
103
+
104
+ val count = Signal[Int]("count")
105
+ val username = Signal[String]("username")
106
+
107
+ div(
108
+ dataSignals(count := 0),
109
+ dataText := count
110
+ )(
111
+ span()("Count: "),
112
+ button(dataOn.click := js"$count++")("Increment")
113
+ )
114
+ ```
115
+
116
+ Datastar expression positions are intentionally stricter than generic HTML/JS templating.
117
+ Raw `String` values are rejected in Datastar expression attributes; use `js"..."`
118
+ for expressions, or typed values like `Signal`, `SignalUpdate`, and `DatastarRef`.
119
+
120
+ ```scala
121
+ dataText := count
122
+ dataText := count.ref
123
+ dataOn.click := js"$count++"
124
+
125
+ // does not compile:
126
+ // dataOn.click := "$count++"
127
+ ```
128
+
129
+ ### Available Attributes
130
+
131
+ | Method | Datastar Attribute | Description |
132
+ |--------|-------------------|-------------|
133
+ | `dataSignals(signal)` | `data-signals:name` | Declare one keyed signal with an initial value |
134
+ | `dataSignals(update, updates...)` | `data-signals` | Patch multiple signals with one object expression |
135
+ | `dataBind(signal)` | `data-bind:name` | Two-way bind an input to a signal |
136
+ | `dataText` | `data-text` | Set element text content |
137
+ | `dataShow` | `data-show` | Conditionally show/hide element |
138
+ | `dataClass("name")` | `data-class:name` | Toggle CSS class |
139
+ | `dataOn.click` | `data-on:click` | Event handler |
140
+ | `dataComputed(signal)` | `data-computed:name` | Computed signal |
141
+ | `dataEffect` | `data-effect` | Side-effect expression |
142
+ | `dataIndicator(signal)` | `data-indicator:name` | Loading indicator signal |
143
+ | `dataRef("name")` | `data-ref:name` | Element reference |
144
+ | `dataInit` | `data-init` | Initialization expression |
145
+
146
+ ### Event Modifiers
147
+
148
+ Chain modifiers on `dataOn` before assigning a handler:
149
+
150
+ ```scala
151
+ // Debounce input by 300ms
152
+ dataOn.input.debounce(300) := username
153
+
154
+ // Click with prevent default, only once
155
+ dataOn.click.prevent.once := js"handleSubmit()"
156
+
157
+ // Throttle scroll, listen on window
158
+ dataOn.scroll.throttle(100).window := js"onScroll()"
159
+ ```
160
+
161
+ Available modifiers: `debounce`, `debounceLeading`, `throttle`, `throttleLeading`, `delay`, `once`, `passive`, `capture`, `stop`, `prevent`, `outside`, `window`, `document`, `viewTransition`.
162
+
163
+ ### Case Modifiers
164
+
165
+ `dataOn` and `dataSignals(signal)` builders expose `.camel`, `.kebab`, `.snake`, and `.pascal` to control how the attribute key is cased. The default for `dataOn` is kebab; for `dataSignals(signal)` it is camel.
166
+
167
+ ```scala
168
+ // Renders data-on:myCustomEvent (camel, explicit)
169
+ dataOn("myCustomEvent").camel := js"handleIt()"
170
+
171
+ // Renders data-signals:my-signal__case.kebab (kebab override)
172
+ dataSignals(count := 0).kebab
173
+ ```
174
+
175
+ The suffix `__case.<modifier>` is appended to the attribute name only when the chosen case differs from the builder's default.
176
+
177
+ ### Advanced Triggers
178
+
179
+ #### dataOnIntersect
180
+
181
+ Fires when the element enters (or exits) the viewport. Modifiers map directly to Datastar's intersection observer options:
182
+
183
+ ```scala
184
+ // Fire once when 50% of the element is visible
185
+ div(dataOnIntersect.half.once := js"loadContent()")()
186
+
187
+ // Fire when element exits the viewport, debounced
188
+ div(dataOnIntersect.exit.debounce(200) := js"cleanup()")()
189
+ ```
190
+
191
+ Available modifiers: `once`, `half`, `full`, `exit`, `threshold(pct: Double)`, `delay(millis)`, `debounce(millis)`, `throttle(millis)`, `viewTransition`.
192
+
193
+ #### dataOnInterval
194
+
195
+ Runs an expression on a repeating timer:
196
+
197
+ ```scala
198
+ // Poll every second
199
+ div(dataOnInterval.duration(1000) := js"$count++")(count.ref.text)
200
+
201
+ // Leading-edge interval with view transitions
202
+ div(dataOnInterval.durationLeading(500).viewTransition := js"refresh()")()
203
+ ```
204
+
205
+ #### dataOnSignalPatch / dataOnSignalPatchFilter
206
+
207
+ `dataOnSignalPatch` runs whenever the server patches signals. Use `dataOnSignalPatchFilter` to restrict which patches trigger the handler:
208
+
209
+ ```scala
210
+ div(
211
+ dataOnSignalPatch.debounce(100) := js"onPatch()",
212
+ dataOnSignalPatchFilter := js"$count > 0"
213
+ )()
214
+ ```
215
+
216
+ Available modifiers on `dataOnSignalPatch`: `delay(millis)`, `debounce(millis)`, `throttle(millis)`.
217
+
218
+ ### Style and Attribute Binding
219
+
220
+ #### dataStyle
221
+
222
+ Bind inline styles, either as a whole-object expression or per-property:
223
+
224
+ ```scala
225
+ // Keyed: sets a single CSS property
226
+ div(dataStyle("color") := js"$isDark ? 'white' : 'black'")()
227
+
228
+ // Unkeyed: bind an entire style object
229
+ div(dataStyle := js"{color: $color, fontSize: $size + 'px'}")()
230
+ ```
231
+
232
+ #### dataAttr
233
+
234
+ Bind arbitrary HTML attributes:
235
+
236
+ ```scala
237
+ div(dataAttr("aria-label") := js"$label")()
238
+ div(dataAttr("tabindex") := js"$isActive ? 0 : -1")()
239
+ ```
240
+
241
+ ### Morph Control
242
+
243
+ Mark elements so Datastar's morphing algorithm treats them specially:
244
+
245
+ ```scala
246
+ // Exclude element and its children from morphing
247
+ div(dataIgnore)()
248
+
249
+ // Exclude only the element itself, not its children
250
+ div(dataIgnoreSelf)()
251
+
252
+ // Prevent the element from being morphed (keep existing DOM node)
253
+ div(dataIgnoreMorph)()
254
+
255
+ // Preserve a specific attribute across morphs
256
+ input(dataPreserveAttr("value"))()
257
+ ```
258
+
259
+ ### JSON Signals
260
+
261
+ `dataJsonSignals` passes a raw JSON string as the signals expression, useful when signals are serialized server-side:
262
+
263
+ ```scala
264
+ div(dataJsonSignals := js"""{"count":0,"username":""}""")()
265
+ ```
266
+
267
+ ## ElementPatchMode
268
+
269
+ Controls how `patchElements` applies DOM content to the target:
270
+
271
+ | Mode | Description |
272
+ |------|-------------|
273
+ | `Outer` | Morphs the target element in place (default, omitted from SSE) |
274
+ | `Inner` | Replaces the target's children |
275
+ | `Replace` | Replaces the target element |
276
+ | `Prepend` | Inserts before the first child |
277
+ | `Append` | Inserts after the last child |
278
+ | `Before` | Inserts before the target element |
279
+ | `After` | Inserts after the target element |
280
+ | `Remove` | Removes the target element |
281
+
282
+ ```scala
283
+ DatastarEvent
284
+ .patchElements(li(id := "new")("item"))
285
+ .withSelector(CssSelector.id("list"))
286
+ .withMode(ElementPatchMode.Append)
287
+ .renderSSE
288
+ ```
289
+
290
+ ## CssSelector
291
+
292
+ `CssSelector` (from `zio.blocks.html`) constructs CSS selectors with type-safe combinators:
293
+
294
+ ```scala
295
+ import zio.blocks.html._
296
+
297
+ CssSelector.id("main") // #main
298
+ CssSelector.`class`("active") // .active
299
+ CssSelector.element("div") // div
300
+ CssSelector.raw(".foo > .bar") // .foo > .bar
301
+ CssSelector.universal // *
302
+ ```
303
+
304
+ Selectors compose with operators:
305
+
306
+ ```scala
307
+ val sel = CssSelector.element("ul") > CssSelector.element("li") // ul > li
308
+ val grouped = CssSelector.id("a") | CssSelector.id("b") // #a, #b
309
+ ```
310
+
311
+ ## Signal.dynamic
312
+
313
+ `Signal[A]("name")` validates the signal name at compile time for string literals. Use `Signal.dynamic[A](name)` when the name is only known at runtime:
314
+
315
+ ```scala
316
+ val fieldName = computeFieldName() // runtime string
317
+ val sig = Signal.dynamic[String](fieldName) // validated at runtime
318
+
319
+ sig := "hello" // works like any other Signal
320
+ ```
321
+
322
+ `dynamic` throws `IllegalArgumentException` if the name is invalid. The same validation rules apply: dot-separated JavaScript identifiers, no `__`.
323
+
324
+ ## SSE Streaming
325
+
326
+ `DatastarEvent` has no ZIO or HTTP framework dependency. It just produces strings. To stream events, set the response content-type to `text/event-stream` and write each `renderSSE` result to the response body:
327
+
328
+ ```scala
329
+ // Framework-agnostic pseudocode
330
+ response.setHeader("Content-Type", "text/event-stream")
331
+ response.setHeader("Cache-Control", "no-cache")
332
+
333
+ // Send an initial signal patch
334
+ response.write(DatastarEvent.patchSignals(count := 0).renderSSE)
335
+
336
+ // Stream DOM updates as data changes
337
+ val fragment = div(id := "result")(computedContent)
338
+ response.write(
339
+ DatastarEvent
340
+ .patchElements(fragment)
341
+ .withSelector(CssSelector.id("result"))
342
+ .renderSSE
343
+ )
344
+ ```
345
+
346
+ Each `renderSSE` call returns a self-contained SSE block — multiple events can be written sequentially to the same stream.