Skip to content

Commit 6f3b19e

Browse files
authored
Merge pull request #4 from falcoframework/task/ds-beta11
2 parents 704a27b + 533ab85 commit 6f3b19e

19 files changed

Lines changed: 324 additions & 331 deletions

File tree

.github/workflows/sdk-dotnet-nuget.yml

Lines changed: 0 additions & 45 deletions
This file was deleted.

README.md

Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let demo =
1414
```
1515

1616
[Falco.Datastar](https://github.com/SpiralOSS/Falco.Datastar) brings type-safe [Datastar](https://data-star.dev) support to [Falco](https://github.com/pimbrouwers/Falco).
17-
It provides a complete mapping of all [plugin attributes](https://data-star.dev/reference/attribute_plugins) and [plugin actions](#https://data-star.dev/reference/action_plugins).
17+
It provides a complete mapping of all [attribute plugins](https://data-star.dev/reference/attribute_plugins) and [action plugins](https://data-star.dev/reference/action_plugins).
1818
As well as helpers for retrieving the signals and responding with Datastar Server Side Events.
1919

2020
## Key Features
@@ -127,7 +127,7 @@ Some important notes: Signals defined later in the DOM tree override those defin
127127
- [Miscellaneous Actions](#miscellaneous-actions)
128128
- [When to $](#when-to-)
129129

130-
### _Creating Signals_
130+
## _Creating Signals_
131131

132132
Create signals, which are reactive variables that automatically propagate their value to all references of the signal.
133133

@@ -151,7 +151,7 @@ As a convenience, you can create a single signal with the option to add it only
151151
**Important note**: if you use kebab-case, it will be returned in pascal-case.
152152

153153
```fsharp
154-
Elem.div [ Ds.signal ("signalPath", "signalValue", ifMissing = true) ] []
154+
Elem.div [ Ds.signal (sp"signalPath", "signalValue", ifMissing = true) ] []
155155
```
156156

157157
### [Ds.computed : `data-computed`](https://data-star.dev/reference/attribute_plugins#data-computed)
@@ -194,7 +194,7 @@ The previous example uses a couple functions we haven't covered yet. [`Ds.onClic
194194
[`Ds.attr'`](#dsattr--data-attr) and [`Ds.show`](#dsshow--data-show) are evaluating the Datastar expression `$fetching` and are assigning `disabled` attribute and
195195
show/hiding the div, respectively, based on the `fetching` signal value's "true-ness".
196196

197-
### _Signal Binding_
197+
## _Signal Binding_
198198

199199
Binding to a signal means tying an attribute or value of an element to a value that can be modified by another effect.
200200
Example: setting the innerText of a `<div>` to a value that is updated by a server; or, toggling an HTML `class` on an element.
@@ -228,7 +228,7 @@ Elem.div [ Ds.attr' "title" "$foo" ] []
228228

229229
### [Ds.show : `data-show`](https://data-star.dev/reference/attribute_plugins#data-show)
230230

231-
Show or hides an element based on whether an expression evaluates to true or false.
231+
Show or hides an element based on whether a [Datastar expression](https://data-star.dev/guide/datastar_expressions) evaluates to true or false.
232232
For anything with custom requirements, use [`data-class`](#dsclass--data-class) instead.
233233

234234
```fsharp
@@ -237,16 +237,15 @@ Elem.div [ Ds.show "$foo" ] []
237237

238238
### [Ds.class' : `data-class`](https://data-star.dev/reference/attribute_plugins#data-class)
239239

240-
Adds or removes a class to or from an element based on the "true-ness" of an expression.
240+
Adds or removes a class to or from an element based on the "true-ness" of a [Datastar expression](https://data-star.dev/guide/datastar_expressions).
241241

242242
```fsharp
243-
Elem.div [ Ds.class' "hidden" "$foo" ]
243+
Elem.div [ Ds.class' "hidden" "$foo" ] // add the 'hidden' class when $foo evaluates to true
244244
```
245245

246-
### [`data-view-transition`](https://data-star.dev/reference/attribute_plugins#data-view-transition)
246+
### [Ds.viewTransition : `data-view-transition`](https://data-star.dev/reference/attribute_plugins#data-view-transition)
247247

248-
Sets the [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) style attribute
249-
explicitly.
248+
Sets the [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) style attribute explicitly.
250249

251250
```fsharp
252251
Elem.div [ Ds.viewTransition "$foo" ]
@@ -266,51 +265,39 @@ Elem.form [] [
266265
]
267266
```
268267

269-
### _Events and Triggers_
268+
## _Events and Triggers_
270269

271270
Events and triggers result in [Datastar expressions](https://data-star.dev/guide/datastar_expressions) being executed. This can possibly result in signal changes and other expressions being run.
272271
Example: clicking a button to send a request or update the visibility on an element via [Ds.show](#dsshow--data-show).
273272

274273
### [Ds.onEvent : `data-on`](https://data-star.dev/reference/attribute_plugins#data-on)
275274

276-
Attaches an event listener to an element, executing an expression whenever the event is triggered.
275+
Attaches an event listener to an element, executing a [Datastar expression](https://data-star.dev/guide/datastar_expressions) whenever the event is triggered.
276+
An `evt` variable that represents the event object is available in the expression.
277277

278278
```fsharp
279-
Elem.div [ Ds.onEvent (SignalsChanged, "$foo = 'updated'") ] []
280-
Elem.div [ Ds.onEvent (Interval, "$show = !$show") ] []
279+
Elem.div [ Ds.onEvent("mouseup", "$selection = document.getSelection().toString()") ] [ Text.raw "Highlight some of me!" ]
280+
Elem.div [ Ds.onEvent("mouseenter", "$show = !$show"); Ds.onEvent("mouseexit", "$show = !$show") ] []
281281
```
282282

283-
```fsharp
284-
type OnEvent =
285-
| Click // Triggered when the element is clicked
286-
| Load // Triggered when the page loads
287-
| Interval // Triggered every 1 second; can be modified with Duration.With(TimeSpan.FromSeconds _)
288-
| RequestAnimationFrame // Triggered on every requestAnimationFrame event. https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
289-
| SignalsChanged // Triggered when any signal changes
290-
| SignalChanged of signalPath:SignalPath // Triggered when a specific signal changes
291-
| Other of string // A custom event; https://developer.mozilla.org/en-US/docs/Web/Events
292-
```
293-
294-
There are helper methods for `Ds.onEvent(Click, ...)` and `Ds.onEvent(Load, ...)`:
283+
There are helper methods for `Ds.onEvent("click", ...)` and `Ds.onEvent("load", ...)`:
295284

296285
```fsharp
297-
Elem.button [ Ds.onClick "$show = !$show" ] [ Text.raw "Hide" ]
286+
Elem.button [ Ds.onClick "$show = !$show" ] [ Text.raw "Peek-a-boo!" ]
298287
Elem.div [ Ds.onLoad (Ds.get "/edit") ] []
299288
```
300289

301-
#### [`data-on` Modifiers](https://data-star.dev/reference/attribute_plugins#modifiers-1)
290+
#### [`data-on` Modifiers](https://data-star.dev/reference/attribute_plugins#modifiers-5)
302291

303-
Modifiers allow you to alter the behavior when events are triggered. (Modifiers with a '*' can only be used with the [built-in events](https://data-star.dev/reference/attribute_plugins#special-events)).
292+
Modifiers allow you to alter the behavior when events are triggered. (Modifiers with a '*' can only be used with the [built-in events](https://developer.mozilla.org/en-US/docs/Web/Events)).
304293

305294
```fsharp
306295
type OnEventModifier =
307296
| Once // * - can only be used with built-in events
308297
| Passive // * - can only be used with built-in events
309298
| Capture // * - can only be used with built-in events
310-
| Delay of TimeSpan
311299
| Debounce of Debounce // timespan, leading, and notrail
312300
| Throttle of Throttle // timepan, noleading, and trail
313-
| Duration of Duration // timespan and leading
314301
| ViewTransition
315302
| Window
316303
| Outside
@@ -321,7 +308,7 @@ Modifiers allow you to alter the behavior when events are triggered. (Modifiers
321308
As an example:
322309
```fsharp
323310
Elem.div [
324-
Ds.onEvent (Click, "$foo = ''", [ Window; Debounce.With(TimeSpan.FromSeconds(1), leading = true) ])
311+
Ds.onEvent ("click", "$foo = ''", [ Window; Debounce.With(TimeSpan.FromSeconds(1.0), leading = true) ])
325312
] []
326313
```
327314

@@ -330,29 +317,63 @@ Results in:
330317
<div data-on-click__window__debounce.1000ms.leading="$foo = ''"></div>
331318
```
332319

333-
### [Ds.intersects : `data-intersects`](https://data-star.dev/reference/attribute_plugins#data-intersects)
320+
### [Ds.onIntersect : `data-on-intersect`](https://data-star.dev/reference/attribute_plugins#data-on-intersect)
334321

335-
Fires an expression when the element intersects with the viewport.
322+
Runs an expression when the element intersects with the viewport.
336323

337324
```fsharp
338-
Elem.div [ Ds.intersects "$intersected = true" ] []
325+
Elem.div [ Ds.onIntersect "$intersected = true" ] []
326+
327+
Elem.div [ Ds.onIntersect ("$intersected = true", visibility = Full) ] []
328+
329+
Elem.div [ Ds.onIntersect ("$intersected = true", visibility = Half, onlyOnce = true) ] []
339330
340-
Elem.div [ Ds.intersects ("$intersected = true", visibility = Full) ] []
331+
Elem.div [ Ds.onIntersect ("$intersected = true", visibility = Half, onlyOnce = true, debounce = Debounce.With(TimeSpan.FromSeconds(1.0))) ] []
341332
342-
Elem.div [ Ds.intersects ("$intersected = true", visibility = Half, onlyOnce = true) ] []
333+
Elem.div [ Ds.onIntersect ("$intersected = true", visibility = Half, onlyOnce = true, throttle = Throttle.With(TimeSpan.FromSeconds(1.0))) ] []
343334
```
344335

345-
### [Ds.scrollIntoView : `data-scroll-into-view`](https://data-star.dev/reference/attribute_plugins#data-scroll-into-view)
336+
### [Ds.onSignalChange | Ds.onAnySignalChange : `data-on-signal-change`](https://data-star.dev/reference/attribute_plugins#data-on-signal-change)
346337

347-
Scrolls the element into view. Useful when updating the DOM from the backend, and you want to scroll to the new content.
338+
Runs an expression when another signal changes. This should be used sparingly, as it is cost intensive.
348339

349340
```fsharp
350-
Elem.div [ Ds.scrollIntoView (Smooth, Center, Center) ] []
341+
Elem.div [ Ds.onAnySignalChange "$show = !$show" ] []
351342
352-
Elem.div [ Ds.scrollIntoView (Auto, Left, Bottom, focus = true) ] []
343+
Elem.div [ Ds.onSignalChange (sp"foo", "$show = !$show") ] []
353344
```
354345

355-
### _Actions and Functions_
346+
### [Ds.onRequestAnimationFrame : `data-on-raf`](https://data-star.dev/reference/attribute_plugins#data-on-raf)
347+
348+
Runs an expression on every request animation frame event.
349+
350+
```fsharp
351+
Elem.div [ Ds.onRequestAnimationFrame "$frame++" ] []
352+
353+
Elem.div [ Ds.onRequestAnimationFrame ("$frame++", debounce = Debounce.With(TimeSpan.FromSeconds(1.0))) ] []
354+
355+
Elem.div [ Ds.onRequestAnimationFrame ("$frame++", throttle = Throttle.With(TimeSpan.FromSeconds(1.0))) ] []
356+
```
357+
358+
### [Ds.onInterval : `data-on-interval`](https://data-star.dev/reference/attribute_plugins#data-on-interval)
359+
360+
Runs an expression at a regular interval. The interval duration defaults to 1 second and can be modified by passing a `TimeSpan`
361+
362+
```fsharp
363+
Elem.div [
364+
Ds.signal (sp"intervalSignalOneSecond", false)
365+
Ds.onInterval "$intervalSignalOneSecond = !$intervalSignalOneSecond"
366+
Ds.text "'One Second Interval = ' + $intervalSignalOneSecond"
367+
] []
368+
369+
Elem.div [
370+
Ds.signal (sp"intervalSignalFiveSecond", false)
371+
Ds.onInterval ("$intervalSignalFiveSecond = !$intervalSignalFiveSecond", TimeSpan.FromSeconds(5.0), leading = true)
372+
Ds.text "'Five Second Interval = ' + $intervalSignalFiveSecond"
373+
] []
374+
```
375+
376+
## _Actions and Functions_
356377

357378
Datastar provides a number of actions and functions that can be used in [Datastar expressions](https://data-star.dev/guide/datastar_expressions)
358379
for making server requests and manipulating signals.
@@ -385,7 +406,7 @@ Each request action can also be provided a number of options, explained in depth
385406

386407
```fsharp
387408
Elem.button [ Ds.onClick (Ds.get ("/endpoint",
388-
{ RequestOptions.defaults with
409+
{ RequestOptions.Defaults with
389410
IncludeLocal = true;
390411
Headers = [ ("X-Csrf-Token", "JImikTbsoCYQ9...") ]
391412
OpenWhenHidden = true }
@@ -418,16 +439,23 @@ Persists signals in local or session storage. Useful for storing values between
418439
Elem.div [ Ds.persistAllSignals ] []
419440
420441
// persist the signals `foo` and `bar` in local storage
421-
Elem.div [ Ds.persistSignals [ "foo"; "bar" ] []
422-
423-
// persist the signals `foo` and `bar` in local storage with "mykey" as the key
424-
Elem.div [ Ds.persistSignals ( [ "foo"; "bar" ], keyName = "mykey") []
442+
Elem.div [ Ds.persistSignals [ sp"foo"; sp"bar" ] ] []
425443
426444
// persist all signals in session storage
427445
Elem.div [ Ds.persistAllSignals (inSession = true) ] []
428446
```
429447

430-
### _Miscellaneous Actions_
448+
### [Ds.scrollIntoView : `data-scroll-into-view`](https://data-star.dev/reference/attribute_plugins#data-scroll-into-view)
449+
450+
Scrolls the element into view. Useful when updating the DOM from the backend, and you want to scroll to the new content.
451+
452+
```fsharp
453+
Elem.div [ Ds.scrollIntoView (Smooth, Center, Center) ] []
454+
455+
Elem.div [ Ds.scrollIntoView (Auto, Left, Bottom, focus = true) ] []
456+
```
457+
458+
## _Miscellaneous Actions_
431459

432460
Helper actions that can be used in [Datastar expressions](https://data-star.dev/guide/datastar_expressions) and performing browser operations.
433461

@@ -481,7 +509,7 @@ Elem.div [ Ds.ignoreThis ] [
481509
]
482510
```
483511

484-
### _When to `$`_
512+
## _When to `$`_
485513

486514
You may have noticed in the sample code that the `$` is used in some places, but not others. At first, it might be
487515
confusing when a `$` is required, but it really isn't all that complicated when you think of the arguments as
@@ -513,7 +541,7 @@ Sections:
513541
- [Responding with HTML Fragments](#responding-with-html-fragments)
514542
- [Streaming Server Side Events](#streaming-server-side-events)
515543

516-
### _Reading Signal Values_
544+
## _Reading Signal Values_
517545

518546
All requests are sent with a `{datastar: *}` object containing the current signals (you can keep signals local to the client
519547
by prefixing the name with an underscore). When using a `GET` request, the signals are sent as a query parameter; otherwise,
@@ -559,7 +587,7 @@ let httpHandler : HttpHandler = (fun ctx -> task {
559587
})
560588
```
561589

562-
### _Responding with Signals_
590+
## _Responding with Signals_
563591

564592
### `Response.ofMergeSignals<'T>`
565593

@@ -593,7 +621,7 @@ Given a `seq` of signal paths, will remove that signals from the client.
593621
Response.ofRemoveSignals [ sp"user.firstName"; sp"user.lastName" ]
594622
```
595623

596-
### _Responding with HTML Fragments_
624+
## _Responding with HTML Fragments_
597625

598626
HTML fragments are sent to client and replace the current element (matching on the `id` attribute) with the one that is sent.
599627
The following functions are `HttpHandler`s that will send down a single Server Sent Event.
@@ -622,7 +650,7 @@ Will send a command to client Datastar to remove fragments with the matching sel
622650
Response.ofRemoveFragments [ sel"hello" ]
623651
```
624652

625-
### _Streaming Server Side Events_
653+
## _Streaming Server Side Events_
626654

627655
Within the `Response` module there are the `of` methods that are for sending single server side events and then closing the connection.
628656
But, [Datastar's](https://data-star.dev) true power is unlocked when the client keep a connection open to the server
@@ -650,4 +678,4 @@ let handleStream = (fun ctx -> task {
650678
counter <- counter + 1
651679
```
652680

653-
See the [Streaming example](examples/Streaming/) for more.
681+
See the [Streaming example](examples/Streaming) for more.

examples/ClickAndSwap/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"Urls": "https://localhost:5001",
2+
"Urls": "http://localhost:5001",
33
"Logging": {
44
"LogLevel": {
55
"Default": "Information"

examples/ClickToEdit/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"Urls": "https://localhost:5001",
2+
"Urls": "http://localhost:5001",
33
"Logging": {
44
"LogLevel": {
55
"Default": "Information"

examples/ClickToLoad/ClickToLoad.fs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ let handleIndex : HttpHandler =
3232
let appendRowsFragmentOptions =
3333
{ MergeFragmentsOptions.defaults
3434
with Selector = ValueSome (sel"#agent_rows")
35-
MergeMode = Append
36-
SettleDuration = TimeSpan.FromSeconds(1L) }
35+
MergeMode = Append }
3736

3837
let handleMoreAgents : HttpHandler = (fun ctx -> task {
3938
// start the text/event-stream
@@ -44,7 +43,7 @@ let handleMoreAgents : HttpHandler = (fun ctx -> task {
4443
let lastAgentShown = lastAgentShown |> ValueOption.get
4544

4645
// remove the button
47-
do! Response.sseRemoveFragments (sse, "#loadMoreAgentsButton", { RemoveFragmentsOptions.defaults with SettleDuration = TimeSpan.Zero })
46+
do! Response.sseRemoveFragments (sse, "#loadMoreAgentsButton")
4847

4948
// N more agents
5049
do!

examples/ClickToLoad/appsettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"Urls": "https://localhost:5001",
2+
"Urls": "http://localhost:5001",
33
"Logging": {
44
"LogLevel": {
55
"Default": "Information"

examples/HelloWorld/HelloWorld.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ let handleIndex : HttpHandler =
1919

2020
let handleClick : HttpHandler =
2121
// create an html fragment which will replace the button with the same `id`
22-
let html = Elem.h2 [ Attr.id "hello" ] [ Text.raw "Hello, World from the Server!" ]
22+
let html = Elem.h2 [ Attr.id "hello" ] [ Text.raw "Hello, World, from the Server!" ]
2323
Response.ofHtmlFragments html
2424

2525
let wapp = WebApplication.Create()

0 commit comments

Comments
 (0)