@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.
- package/adr/2026-07-18-data-migration.md +123 -0
- package/guides/async-getting-started.md +687 -0
- package/guides/compile-time-resource-safety-with-scope.md +21 -16
- package/guides/getting-started-with-mux.md +1395 -0
- package/guides/query-dsl-extending.md +161 -102
- package/guides/query-dsl-fluent-builder.md +217 -157
- package/guides/query-dsl-reified-optics.md +12 -10
- package/guides/query-dsl-sql.md +640 -165
- package/guides/sql-checked-interpolation.md +173 -0
- package/guides/sql-transactions.md +286 -0
- package/guides/telemetry-guide.md +1130 -0
- package/guides/zio-schema-migration.md +29 -22
- package/index.md +248 -389
- package/package.json +1 -1
- package/plans/config-follow-up-prs.md +188 -0
- package/plans/config-pr-assessment-roadmap.md +310 -0
- package/reference/MuxDataFlow.jsx +250 -0
- package/reference/async.md +1499 -0
- package/reference/chunk.md +3533 -308
- package/reference/codegen/case-class.md +436 -0
- package/reference/codegen/emitter-config.md +383 -0
- package/reference/codegen/examples.md +664 -0
- package/reference/codegen/field.md +316 -0
- package/reference/codegen/index.md +317 -0
- package/reference/codegen/scala-emitter.md +392 -0
- package/reference/codegen/scala-file.md +276 -0
- package/reference/codegen/sealed-trait.md +408 -0
- package/reference/codegen/type-definition.md +340 -0
- package/reference/codegen/type-ref.md +201 -0
- package/reference/combinators.md +347 -117
- package/reference/config/config-decoder.md +460 -0
- package/reference/config/config-source.md +489 -0
- package/reference/config/errors.md +278 -0
- package/reference/config/flags.md +369 -0
- package/reference/config/formats.md +314 -0
- package/reference/config/index.md +304 -0
- package/reference/config/rollout.md +336 -0
- package/reference/context.md +9 -52
- package/reference/data-migration.md +269 -0
- package/reference/datastar/attributes.md +302 -0
- package/reference/datastar/events.md +234 -0
- package/reference/datastar/index.md +256 -0
- package/reference/datastar/signals.md +230 -0
- package/reference/datastar/sse.md +295 -0
- package/reference/datastar.md +346 -0
- package/reference/docs.md +1461 -345
- package/reference/endpoint/auth-type.md +146 -0
- package/reference/endpoint/bulk-creation.md +96 -0
- package/reference/endpoint/endpoint.md +297 -0
- package/reference/endpoint/http-codec.md +249 -0
- package/reference/endpoint/index.md +745 -0
- package/reference/endpoint/path-codec.md +225 -0
- package/reference/endpoint/route-pattern.md +194 -0
- package/reference/endpoint/route-tree.md +111 -0
- package/reference/endpoint/segment-codec.md +199 -0
- package/reference/html.md +1424 -0
- package/reference/htmx/attribute-values.md +359 -0
- package/reference/htmx/hx-encoding.md +111 -0
- package/reference/htmx/hx-params.md +204 -0
- package/reference/htmx/hx-swap.md +276 -0
- package/reference/htmx/hx-sync.md +251 -0
- package/reference/htmx/hx-target.md +314 -0
- package/reference/htmx/hx-trigger.md +457 -0
- package/reference/htmx/hx-url-update.md +239 -0
- package/reference/htmx/index.md +807 -0
- package/reference/htmx/response-headers.md +240 -0
- package/reference/http-model/headers.md +735 -0
- package/reference/http-model/index.md +49 -0
- package/reference/http-model/model.md +1517 -0
- package/reference/http-model/schema-codecs.md +522 -0
- package/reference/http-model/schema.md +750 -0
- package/reference/http-model/server-sent-event.md +341 -0
- package/reference/jwt.md +195 -0
- package/reference/maybe.md +943 -0
- package/reference/media-type.md +2 -2
- package/reference/mux.md +254 -0
- package/reference/mux.mdx +828 -0
- package/reference/openapi.md +1351 -0
- package/reference/projection.md +654 -0
- package/reference/resource-management/defer-handle.md +1 -1
- package/reference/resource-management/resource.md +31 -98
- package/reference/resource-management/scope.md +28 -220
- package/reference/resource-management/wire.md +5 -55
- package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
- package/reference/ringbuffer/MpscDiagram.jsx +618 -0
- package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
- package/reference/ringbuffer/SpscDiagram.jsx +677 -0
- package/reference/ringbuffer/advanced.mdx +109 -0
- package/reference/ringbuffer/index.mdx +145 -0
- package/reference/ringbuffer/mpmc.mdx +185 -0
- package/reference/ringbuffer/mpsc.mdx +164 -0
- package/reference/ringbuffer/spmc.mdx +108 -0
- package/reference/ringbuffer/spsc.mdx +416 -0
- package/reference/{allows.md → schema/allows.md} +4 -100
- package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
- package/reference/{binding.md → schema/binding.md} +3 -4
- package/reference/schema/built-in-codecs/avro.md +451 -0
- package/reference/schema/built-in-codecs/bson.md +510 -0
- package/reference/schema/built-in-codecs/csv.md +564 -0
- package/reference/schema/built-in-codecs/index.md +77 -0
- package/reference/schema/built-in-codecs/json/index.md +295 -0
- package/reference/schema/built-in-codecs/json/json-config.md +217 -0
- package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
- package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
- package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
- package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
- package/reference/schema/built-in-codecs/messagepack.md +508 -0
- package/reference/schema/built-in-codecs/thrift.md +433 -0
- package/reference/schema/built-in-codecs/toon.md +1078 -0
- package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
- package/reference/schema/built-in-codecs/yaml.md +552 -0
- package/reference/{codec.md → schema/codec.md} +11 -11
- package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
- package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
- package/reference/schema/format.md +92 -0
- package/reference/schema/index.md +52 -0
- package/reference/schema/migration.md +297 -0
- package/reference/{modifier.md → schema/modifier.md} +58 -7
- package/reference/{optics.md → schema/optics.md} +2 -2
- package/reference/{patch.md → schema/patch.md} +1 -1
- package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
- package/reference/schema/reflect-transformer.md +140 -0
- package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
- package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
- package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
- package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
- package/reference/schema/schema-search.md +263 -0
- package/reference/{schema.md → schema/schema.md} +22 -2
- package/reference/{structural-types.md → schema/structural-types.md} +1 -1
- package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
- package/reference/smithy.md +1032 -0
- package/reference/sql/db-codec-deriver.md +71 -0
- package/reference/sql/db-codec.md +687 -0
- package/reference/sql/db-con.md +271 -0
- package/reference/sql/db-connection.md +153 -0
- package/reference/sql/db-param-writer.md +77 -0
- package/reference/sql/db-param.md +66 -0
- package/reference/sql/db-result-reader.md +148 -0
- package/reference/sql/db-tx.md +114 -0
- package/reference/sql/db-value.md +41 -0
- package/reference/sql/ddl.md +85 -0
- package/reference/sql/frag.md +288 -0
- package/reference/sql/index.md +341 -0
- package/reference/sql/repo.md +600 -0
- package/reference/sql/sql-dialect.md +73 -0
- package/reference/sql/sql-logger.md +62 -0
- package/reference/sql/sql-name-mapper.md +70 -0
- package/reference/sql/table-metadata.md +134 -0
- package/reference/sql/table.md +448 -0
- package/reference/sql/transactor-zio.md +399 -0
- package/reference/sql/transactor.md +363 -0
- package/reference/sql-zio.md +112 -0
- package/reference/streams/core/index.md +32 -0
- package/reference/streams/core/pipeline.md +854 -0
- package/reference/streams/core/sink.md +1404 -0
- package/reference/streams/core/stream.md +3236 -0
- package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
- package/reference/streams/execution-and-compatibility/index.md +35 -0
- package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
- package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
- package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
- package/reference/streams/index.md +726 -0
- package/reference/streams/primitives/index.md +30 -0
- package/reference/streams/primitives/reader.md +1992 -0
- package/reference/streams/primitives/writer.md +1201 -0
- package/reference/telemetry/common/any-value.md +90 -0
- package/reference/telemetry/common/attribute-key.md +87 -0
- package/reference/telemetry/common/attributes.md +118 -0
- package/reference/telemetry/common/index.md +39 -0
- package/reference/telemetry/common/instrumentation-scope.md +24 -0
- package/reference/telemetry/common/resource.md +34 -0
- package/reference/telemetry/index.md +311 -0
- package/reference/telemetry/logging/index.md +197 -0
- package/reference/telemetry/logging/log-enrichment.md +72 -0
- package/reference/telemetry/logging/log-formatter.md +100 -0
- package/reference/telemetry/logging/log-record-processor.md +56 -0
- package/reference/telemetry/logging/log-record.md +44 -0
- package/reference/telemetry/logging/log-writer.md +64 -0
- package/reference/telemetry/logging/logger-provider.md +142 -0
- package/reference/telemetry/logging/logger.md +83 -0
- package/reference/telemetry/logging/severity.md +62 -0
- package/reference/telemetry/metrics/index.md +150 -0
- package/reference/telemetry/metrics/instruments.md +183 -0
- package/reference/telemetry/metrics/labeled-instruments.md +74 -0
- package/reference/telemetry/metrics/meter-provider.md +76 -0
- package/reference/telemetry/metrics/meter.md +98 -0
- package/reference/telemetry/metrics/metric-data.md +57 -0
- package/reference/telemetry/otel/custom-exporter.md +216 -0
- package/reference/telemetry/otel/index.md +212 -0
- package/reference/telemetry/tracing/index.md +155 -0
- package/reference/telemetry/tracing/sampler.md +89 -0
- package/reference/telemetry/tracing/span-builder.md +57 -0
- package/reference/telemetry/tracing/span-context.md +39 -0
- package/reference/telemetry/tracing/span-data.md +32 -0
- package/reference/telemetry/tracing/span-kind.md +55 -0
- package/reference/telemetry/tracing/span-processor.md +53 -0
- package/reference/telemetry/tracing/span-status.md +47 -0
- package/reference/telemetry/tracing/span.md +117 -0
- package/reference/telemetry/tracing/tracer-provider.md +91 -0
- package/reference/telemetry/tracing/tracer.md +52 -0
- package/reference/typeid.md +5 -83
- package/sidebars.js +376 -43
- package/undocumented-report.md +528 -270
- package/reference/formats.md +0 -694
- package/reference/http-model.md +0 -1716
- package/reference/streams.md +0 -989
- package/ringbuffer.md +0 -249
- /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
- /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
- /package/reference/{lazy.md → schema/lazy.md} +0 -0
- /package/reference/{reflect.md → schema/reflect.md} +0 -0
- /package/reference/{registers.md → schema/registers.md} +0 -0
- /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
- /package/reference/{syntax.md → schema/syntax.md} +0 -0
- /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.
|