Remove settling from SSE events and SDKs (#764)

* Remove settling

* Add release note

* Bump PHP SDK version

* Remove from composer
This commit is contained in:
Ben Croker 2025-03-15 16:25:33 -06:00 committed by GitHub
parent 39cb56db3e
commit c35b85ce4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
79 changed files with 90 additions and 522 deletions

View File

@ -19,3 +19,7 @@ Each tagged version of Datastar is accompanied by a release note. Read the [rele
- Fixed the applying of plugins to give custom plugins a chance to load ([#740](https://github.com/starfederation/datastar/issues/740)).
- Fixed a bug in which the indicator signal was not being reset when the element it was on was removed from the DOM ([#749](https://github.com/starfederation/datastar/issues/749)).
### Removed
- Removed settling entirely from SSE events, since it has become redundant ([#764](https://github.com/starfederation/datastar/issues/764)).

View File

@ -10,7 +10,7 @@
Datastar helps you build reactive web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.
Getting started is as easy as adding a single 14.6 KiB script tag to your HTML.
Getting started is as easy as adding a single 14.4 KiB script tag to your HTML.
```html
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.9/bundles/datastar.js"></script>

View File

@ -148,11 +148,6 @@ var Consts = &ConstTemplateData{
},
},
DefaultDurations: []*DefaultDuration{
{
Name: toolbelt.ToCasedString("fragmentsSettleDuration"),
Description: "The default duration for settling during fragment merges. Allows for CSS transitions to complete.",
Duration: 300 * time.Millisecond,
},
{
Name: toolbelt.ToCasedString("sseRetryDuration"),
Description: "The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.",
@ -172,7 +167,6 @@ var Consts = &ConstTemplateData{
// MergeFragments
toolbelt.ToCasedString("mergeMode"),
toolbelt.ToCasedString("settleDuration"),
toolbelt.ToCasedString("fragments"),
toolbelt.ToCasedString("useViewTransition"),

View File

@ -7,7 +7,6 @@ export const DSP = lol.slice(0, 5)
export const DSS = lol.slice(4)
export const DATASTAR = "{%s data.DatastarKey %}";
export const DATASTAR_EVENT = "{%s data.DatastarKey %}-event";
export const DATASTAR_REQUEST = "{%s toolbelt.Pascal( data.DatastarKey) %}-Request";
// #region Defaults

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
Datastar helps you build reactive web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.
Getting started is as easy as adding a single 14.6 KiB script tag to your HTML.
Getting started is as easy as adding a single 14.4 KiB script tag to your HTML.
```html
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.9/bundles/datastar.js"></script>

View File

@ -4,15 +4,12 @@ export const DSP = lol.slice(0, 5)
export const DSS = lol.slice(4)
export const DATASTAR = "datastar";
export const DATASTAR_EVENT = "datastar-event";
export const DATASTAR_REQUEST = "Datastar-Request";
// #region Defaults
// #region Default durations
// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
export const DefaultFragmentsSettleDurationMs = 300;
// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
export const DefaultSseRetryDurationMs = 1000;

View File

@ -1,8 +1,6 @@
import { DATASTAR } from '../../../engine/consts'
export const DATASTAR_SSE_EVENT = `${DATASTAR}-sse`
export const SETTLING_CLASS = `${DATASTAR}-settling`
export const SWAPPING_CLASS = `${DATASTAR}-swapping`
export const STARTED = 'started'
export const FINISHED = 'finished'
export const ERROR = 'error'

View File

@ -4,7 +4,6 @@
import {
DefaultFragmentMergeMode,
DefaultFragmentsSettleDurationMs,
DefaultFragmentsUseViewTransitions,
EventTypes,
FragmentMergeModes,
@ -23,11 +22,7 @@ import {
supportsViewTransitions,
} from '../../../../utils/view-transtions'
import { Idiomorph } from '../../../../vendored/idiomorph.esm'
import {
SETTLING_CLASS,
SWAPPING_CLASS,
datastarSSEEventWatcher,
} from '../shared'
import { datastarSSEEventWatcher } from '../shared'
export const MergeFragments: WatcherPlugin = {
type: PluginType.Watcher,
@ -40,12 +35,9 @@ export const MergeFragments: WatcherPlugin = {
fragments: fragmentsRaw = '<div></div>',
selector = '',
mergeMode = DefaultFragmentMergeMode,
settleDuration:
settleDurationRaw = `${DefaultFragmentsSettleDurationMs}`,
useViewTransition:
useViewTransitionRaw = `${DefaultFragmentsUseViewTransitions}`,
}) => {
const settleDuration = Number.parseInt(settleDurationRaw)
const useViewTransition = isBoolString(useViewTransitionRaw)
fragmentContainer.innerHTML = fragmentsRaw.trim()
@ -63,10 +55,10 @@ export const MergeFragments: WatcherPlugin = {
if (useViewTransition && supportsViewTransitions) {
docWithViewTransitionAPI.startViewTransition(() =>
applyToTargets(ctx, mergeMode, settleDuration, fragment, targets),
applyToTargets(ctx, mergeMode, fragment, targets),
)
} else {
applyToTargets(ctx, mergeMode, settleDuration, fragment, targets)
applyToTargets(ctx, mergeMode, fragment, targets)
}
}
},
@ -77,14 +69,10 @@ export const MergeFragments: WatcherPlugin = {
function applyToTargets(
ctx: InitContext,
mergeMode: string,
settleDuration: number,
fragment: Element,
capturedTargets: Element[],
) {
for (const initialTarget of capturedTargets) {
initialTarget.classList.add(SWAPPING_CLASS)
const originalHTML = initialTarget.outerHTML
const modifiedTarget = initialTarget
for (const target of capturedTargets) {
switch (mergeMode) {
case FragmentMergeModes.Morph: {
const fragmentWithIDs = fragment.cloneNode(true) as HTMLorSVGElement
@ -105,59 +93,42 @@ function applyToTargets(
}
})
Idiomorph.morph(modifiedTarget, fragmentWithIDs)
Idiomorph.morph(target, fragmentWithIDs)
break
}
case FragmentMergeModes.Inner:
// Replace the contents of the target element with the outer HTML of the response
modifiedTarget.innerHTML = fragment.outerHTML
target.innerHTML = fragment.outerHTML
break
case FragmentMergeModes.Outer:
// Replace the entire target element with the response
modifiedTarget.replaceWith(fragment)
target.replaceWith(fragment)
break
case FragmentMergeModes.Prepend:
// Insert the response before the first child of the target element
modifiedTarget.prepend(fragment)
target.prepend(fragment)
break
case FragmentMergeModes.Append:
// Insert the response after the last child of the target element
modifiedTarget.append(fragment)
target.append(fragment)
break
case FragmentMergeModes.Before:
// Insert the response before the target element
modifiedTarget.before(fragment)
target.before(fragment)
break
case FragmentMergeModes.After:
// Insert the response after the target element
modifiedTarget.after(fragment)
target.after(fragment)
break
case FragmentMergeModes.UpsertAttributes:
// Upsert the attributes of the target element
for (const attrName of fragment.getAttributeNames()) {
const value = fragment.getAttribute(attrName)!
modifiedTarget.setAttribute(attrName, value)
target.setAttribute(attrName, value)
}
break
default:
throw initErr('InvalidMergeMode', ctx, { mergeMode })
}
const cl = modifiedTarget.classList
cl?.add(SWAPPING_CLASS)
setTimeout(() => {
initialTarget.classList.remove(SWAPPING_CLASS)
cl?.remove(SWAPPING_CLASS)
}, settleDuration)
const revisedHTML = modifiedTarget.outerHTML
if (cl && originalHTML !== revisedHTML) {
cl.add(SETTLING_CLASS)
setTimeout(() => {
cl.remove(SETTLING_CLASS)
}, settleDuration)
}
}
}

View File

@ -3,7 +3,6 @@
// Description: Remember, SSE is just a regular SSE request but with the ability to send 0-inf messages to the client.
import {
DefaultFragmentsSettleDurationMs,
DefaultFragmentsUseViewTransitions,
EventTypes,
} from '../../../../engine/consts'
@ -14,7 +13,7 @@ import {
docWithViewTransitionAPI,
supportsViewTransitions,
} from '../../../../utils/view-transtions'
import { SWAPPING_CLASS, datastarSSEEventWatcher } from '../shared'
import { datastarSSEEventWatcher } from '../shared'
export const RemoveFragments: WatcherPlugin = {
type: PluginType.Watcher,
@ -24,8 +23,6 @@ export const RemoveFragments: WatcherPlugin = {
EventTypes.RemoveFragments,
({
selector,
settleDuration:
settleDurationRaw = `${DefaultFragmentsSettleDurationMs}`,
useViewTransition:
useViewTransitionRaw = `${DefaultFragmentsUseViewTransitions}`,
}) => {
@ -33,20 +30,13 @@ export const RemoveFragments: WatcherPlugin = {
throw initErr('NoSelectorProvided', ctx)
}
const settleDuration = Number.parseInt(settleDurationRaw)
const useViewTransition = isBoolString(useViewTransitionRaw)
const removeTargets = document.querySelectorAll(selector)
const applyToTargets = () => {
for (const target of removeTargets) {
target.classList.add(SWAPPING_CLASS)
}
setTimeout(() => {
for (const target of removeTargets) {
target.remove()
}
}, settleDuration)
}
if (useViewTransition && supportsViewTransitions) {

View File

@ -87,7 +87,6 @@ ServerSentEventGenerator.MergeFragments(
options?: {
selector?: string,
mergeMode?: FragmentMergeMode,
settleDuration?: durationInMilliseconds,
useViewTransition?: boolean,
eventId?: string,
retryDuration?: durationInMilliseconds
@ -113,7 +112,6 @@ event: datastar-merge-fragments
id: 123
retry: 2000
data: selector #feed
data: settleDuration 10
data: useViewTransition true
data: fragments <div id="feed">
data: fragments <span>1</span>
@ -143,16 +141,14 @@ Valid values should match the [FragmentMergeMode](#FragmentMergeMode) and curren
##### Options
* `selector` (string) The CSS selector to use to insert the fragments. If not provided or empty, Datastar **will** default to using the `id` attribute of the fragment.
* `mergeMode` (FragmentMergeMode) The mode to use when merging the fragment into the DOM. If not provided the Datastar client side ***will*** default to `morph`.
* `settleDuration` is used to control the amount of time that a fragment should take before removing any CSS related to settling. It is used to allow for animations in the browser via the Datastar client. If provided the value ***must*** be a positive integer of the number of milliseconds to allow for settling. If none is provided, the default value of `300` milliseconds will be used.
* `useViewTransition` Whether to use view transitions, if not provided the Datastar client side ***will*** default to `false`.
#### Logic
When called the function ***must*** call `ServerSentEventGenerator.send` with the `datastar-merge-fragments` event type.
1. If `selector` is provided, the function ***must*** include the selector in the event data in the format `selector SELECTOR\n`, ***unless*** the selector is empty.
2. If `mergeMode` is provided, the function ***must*** include the merge mode in the event data in the format `merge MERGE_MODE\n`, ***unless*** the value is the default of `morph`.
3. If `settleDuration` is provided, the function ***must*** include the settle duration in the event data in the format `settleDuration SETTLE_DURATION\n`, ***unless*** the value is the default of `300` milliseconds.
4. If `useViewTransition` is provided, the function ***must*** include the view transition in the event data in the format `useViewTransition USE_VIEW_TRANSITION\n`, ***unless*** the value is the default of `false`. `USE_VIEW_TRANSITION` should be `true` or `false` (string), depending on the value of the `useViewTransition` option.
5. The function ***must*** include the fragments in the event data, with each line prefixed with `fragments `. This ***should*** be output after all other event data.
3. If `useViewTransition` is provided, the function ***must*** include the view transition in the event data in the format `useViewTransition USE_VIEW_TRANSITION\n`, ***unless*** the value is the default of `false`. `USE_VIEW_TRANSITION` should be `true` or `false` (string), depending on the value of the `useViewTransition` option.
4. The function ***must*** include the fragments in the event data, with each line prefixed with `fragments `. This ***should*** be output after all other event data.
### `ServerSentEventGenerator.RemoveFragments`
@ -160,7 +156,6 @@ When called the function ***must*** call `ServerSentEventGenerator.send` with th
ServerSentEventGenerator.RemoveFragments(
selector: string,
options?: {
settleDuration?: durationInMilliseconds,
useViewTransition?: boolean,
eventId?: string,
retryDuration?: durationInMilliseconds
@ -184,7 +179,6 @@ event: datastar-remove-fragments
id: 123
retry: 2000
data: selector #target
data: settleDuration 200
data: useViewTransition true
```
@ -196,14 +190,12 @@ data: useViewTransition true
##### Options
* `settleDuration` is used to control the amount of time that a fragment should take before removing any CSS related to settling. It is used to allow for animations in the browser via the Datastar client. If provided the value ***must*** be a positive integer of the number of milliseconds to allow for settling. If none is provided, the default value of `300` milliseconds will be used.
* `useViewTransition` Whether to use view transitions, if not provided the Datastar client side ***will*** default to `false`.
#### Logic
1. When called the function ***must*** call `ServerSentEventGenerator.send` with the `datastar-remove-fragments` event type.
2. The function ***must*** include the selector in the event data in the format `selector SELECTOR\n`.
3. If `settleDuration` is provided, the function ***must*** include the settle duration in the event data in the format `settleDuration SETTLE_DURATION\n`, ***unless*** the value is the default of `300` milliseconds.
4. If `useViewTransition` is provided, the function ***must*** include the view transition in the event data in the format `useViewTransition USE_VIEW_TRANSITION\n`, ***unless*** the value is the default of `false`. `USE_VIEW_TRANSITION` should be `true` or `false` (string), depending on the value of the `useViewTransition` option.
3. If `useViewTransition` is provided, the function ***must*** include the view transition in the event data in the format `useViewTransition USE_VIEW_TRANSITION\n`, ***unless*** the value is the default of `false`. `USE_VIEW_TRANSITION` should be `true` or `false` (string), depending on the value of the `useViewTransition` option.
### `ServerSentEventGenerator.MergeSignals`

View File

@ -59,7 +59,6 @@
[:map
[common/selector :string]
[common/merge-mode merge-modes-schema]
[common/settle-duration number?]
[common/use-view-transition :boolean]])))
;; -----------------------------------------------------------------------------
@ -70,7 +69,6 @@
sse-options-schema
(mu/optional-keys
[:map
[common/settle-duration number?]
[common/use-view-transition :boolean]])))

View File

@ -42,7 +42,6 @@
"selector" d*/selector
"mergeMode" d*/merge-mode
"useViewTransition" d*/use-view-transition
"settleDuration" d*/settle-duration
"onlyIfMissing" d*/only-if-missing
"autoRemove" d*/auto-remove

View File

@ -14,7 +14,6 @@ These function take options map whose keys are:
- [[retry-duration]]
- [[selector]]
- [[merge-mode]]
- [[settle-duration]]
- [[use-view-transition]]
- [[only-if-missing]]
- [[auto-remove]]
@ -155,16 +154,6 @@ Some scripts are provided:
"
common/merge-mode)
(def settle-duration
"[[merge-fragment!]] / [[remove-fragment!]] option, number:
Used to control the amount of time that a fragment
should take before removing any CSS related to settling. It is used to allow
for animations in the browser via the Datastar client. If provided the value must
be a positive integer of the number of milliseconds to allow for settling. If none
is provided, the default value of 300 milliseconds will be used."
common/settle-duration)
(def use-view-transition
"[[merge-fragment!]] / [[remove-fragment!] option, boolean:
@ -247,7 +236,6 @@ Some scripts are provided:
- [[retry-duration]]
- [[selector]]
- [[merge-mode]]
- [[settle-duration]]
- [[use-view-transition]]
Return value:
@ -282,7 +270,6 @@ Some scripts are provided:
Options keys:
- [[id]]
- [[retry-duration]]
- [[settle-duration]]
- [[use-view-transition]]
Return value:

View File

@ -11,7 +11,6 @@
;; Merge fragment opts
(def selector :d*.fragments/selector)
(def merge-mode :d*.fragments/merge-mode)
(def settle-duration :d*.fragments/settle-duration)
(def use-view-transition :d*.fragments/use-view-transition)
;;Signals opts

View File

@ -39,19 +39,6 @@
fmm))
;; -----------------------------------------------------------------------------
;; Settle duration helpers
(defn- add-settle-duration? [d]
(and d (> d consts/default-fragments-settle-duration)))
(defn- add-settle-duration?! [data-lines! d]
(common/add-opt-line!
data-lines!
add-settle-duration?
consts/settle-duration-dataline-literal
d))
;; -----------------------------------------------------------------------------
;; View transition helpers
(defn add-view-transition? [val]
@ -81,7 +68,6 @@
(u/transient-> []
(add-selector?! (common/selector opts))
(add-fragment-merge-mode?! (common/merge-mode opts))
(add-settle-duration?! (common/settle-duration opts))
(add-view-transition?! (common/use-view-transition opts))
(add-merge-fragment! fragment)))
@ -93,11 +79,9 @@
(->merge-fragment "<div>hello</div> \n<div>world!!!</div>"
{common/selector "#toto"
common/merge-mode consts/fragment-merge-mode-after
common/settle-duration 500
common/use-view-transition :toto})
:= ["selector #toto"
"mergeMode after"
"settleDuration 500"
"useViewTransition true"
"fragments <div>hello</div> "
"fragments <div>world!!!</div>"])
@ -131,7 +115,6 @@
(u/transient-> []
(add-selector?! (common/selector opts))
(add-fragment-merge-mode?! (common/merge-mode opts))
(add-settle-duration?! (common/settle-duration opts))
(add-view-transition?! (common/use-view-transition opts))
(add-merge-fragments! fragments)))
@ -158,11 +141,9 @@
(->merge-fragments ["<div>hello</div> \n<div>world!!!</div>" "<div>world!!!</div>"]
{common/selector "#toto"
common/merge-mode consts/fragment-merge-mode-after
common/settle-duration 500
common/use-view-transition true})
:= ["selector #toto"
"mergeMode after"
"settleDuration 500"
"useViewTransition true"
"fragments <div>hello</div> "
"fragments <div>world!!!</div>"
@ -174,16 +155,14 @@
;; -----------------------------------------------------------------------------
(defn ->remove-fragment [selector opts]
(u/transient-> []
(add-settle-duration?! (common/settle-duration opts))
(add-view-transition?! (common/use-view-transition opts))
(add-selector! selector)))
(comment
(->remove-fragment "#titi"
{common/settle-duration 500
common/use-view-transition true})
:= ["selector #titi" "settleDuration 500" "useViewTransition true"])
{common/use-view-transition true})
:= ["selector #titi" "useViewTransition true"])
(defn remove-fragment! [sse-gen selector opts]

View File

@ -11,10 +11,6 @@
;; -----------------------------------------------------------------------------
;; Default durations
;; -----------------------------------------------------------------------------
(def default-fragments-settle-duration
"The default duration for settling during fragment merges. Allows for CSS transitions to complete."
300)
(def default-sse-retry-duration
"The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE."
1000)
@ -36,7 +32,6 @@
;; -----------------------------------------------------------------------------
(def selector-dataline-literal "selector ")
(def merge-mode-dataline-literal "mergeMode ")
(def settle-duration-dataline-literal "settleDuration ")
(def fragments-dataline-literal "fragments ")
(def use-view-transition-dataline-literal "useViewTransition ")
(def signals-dataline-literal "signals ")

View File

@ -11,7 +11,6 @@
:fragments ["<div>hello</div>"]
d*/selector "foo"
d*/merge-mode d*/mm-append
d*/settle-duration 500
d*/use-view-transition true})
@ -31,7 +30,6 @@
(sse-event example)
; ["selector foo"
; "mergeMode append"
; "settleDuration 500"
; "useViewTransition true"
; "fragments <div>hello</div>"]
@ -60,7 +58,6 @@
; retry: 1000\n
; data: selector foo\n
; data: mergeMode append\n
; data: settleDuration 500\n
; data: useViewTransition true\n
; data: fragments <div>hello</div>\n\n\n"
@ -84,6 +81,5 @@
; retry: 1000\n
; data: selector foo\n
; data: mergeMode append\n
; data: settleDuration 500\n
; data: useViewTransition true\n
; data: fragments <div>hello</div>\n\n\n"

View File

@ -115,10 +115,6 @@
(def merge-mode-line
(->data-line consts/merge-mode-dataline-literal test-merge-mode))
(def test-settle-duration 500)
(def settle-duration-line
(->data-line consts/settle-duration-dataline-literal test-settle-duration))
(def use-view-transition-line
(->data-line consts/use-view-transition-dataline-literal true))
@ -156,13 +152,6 @@
(expect-merge-fragment gen {d*/merge-mode test-merge-mode}
(list* merge-mode-line div-data)))
(it "handles settle duration"
(expect-merge-fragment gen {d*/settle-duration test-settle-duration}
(list* settle-duration-line div-data))
(expect-merge-fragment gen {d*/settle-duration consts/default-fragments-settle-duration}
div-data))
(it "handles view transitions"
(expect-merge-fragment gen {d*/use-view-transition true}
(list* use-view-transition-line div-data))
@ -172,11 +161,9 @@
(it "handles all options"
(expect-merge-fragment gen {d*/selector basic-selector
d*/merge-mode test-merge-mode
d*/settle-duration test-settle-duration
d*/use-view-transition true}
(list* selector-line
merge-mode-line
settle-duration-line
use-view-transition-line
div-data))))))
@ -221,13 +208,6 @@
(expect-merge-fragments gen {d*/merge-mode test-merge-mode}
(list* merge-mode-line multi-data)))
(it "handles settle duration"
(expect-merge-fragments gen {d*/settle-duration test-settle-duration}
(list* settle-duration-line multi-data))
(expect-merge-fragments gen {d*/settle-duration consts/default-fragments-settle-duration}
multi-data))
(it "handles view transitions"
(expect-merge-fragments gen {d*/use-view-transition true}
(list* use-view-transition-line multi-data))
@ -239,11 +219,9 @@
(it "handles all options"
(expect-merge-fragments gen {d*/selector basic-selector
d*/merge-mode test-merge-mode
d*/settle-duration test-settle-duration
d*/use-view-transition true}
(list* selector-line
merge-mode-line
settle-duration-line
use-view-transition-line
multi-data))))))
@ -266,13 +244,6 @@
(it "Throws on no selector"
(expect (lt/throws? clojure.lang.ExceptionInfo #(d*/remove-fragment! gen "" {}))))
(it "handles settle duration"
(expect-remove-fragment gen {d*/settle-duration test-settle-duration}
[settle-duration-line selector-line])
(expect-remove-fragment gen {d*/settle-duration consts/default-fragments-settle-duration}
[selector-line]))
(it "handles view transitions"
(expect-remove-fragment gen {d*/use-view-transition true}
[use-view-transition-line selector-line])
@ -282,10 +253,8 @@
[selector-line]))
(it "handles all options"
(expect-remove-fragment gen {d*/settle-duration test-settle-duration
d*/use-view-transition true}
[settle-duration-line
use-view-transition-line
(expect-remove-fragment gen {d*/use-view-transition true}
[use-view-transition-line
selector-line])))))
;; -----------------------------------------------------------------------------

View File

@ -39,8 +39,6 @@ module Consts =
let [<Literal>] DatastarKey = "datastar"
let [<Literal>] Version = "1.0.0-beta.9"
/// Default: TimeSpan.FromMilliseconds 300
let DefaultFragmentsSettleDuration = TimeSpan.FromMilliseconds 300
/// Default: TimeSpan.FromMilliseconds 1000
let DefaultSseRetryDuration = TimeSpan.FromMilliseconds 1000
@ -56,7 +54,6 @@ module Consts =
let [<Literal>] DatastarDatalineSelector = "selector"
let [<Literal>] DatastarDatalineMergeMode = "mergeMode"
let [<Literal>] DatastarDatalineSettleDuration = "settleDuration"
let [<Literal>] DatastarDatalineFragments = "fragments"
let [<Literal>] DatastarDatalineUseViewTransition = "useViewTransition"
let [<Literal>] DatastarDatalineSignals = "signals"

View File

@ -75,12 +75,10 @@ and ServerSentEventMergeFragmentsOptions() =
member val Retry = Consts.DefaultSseRetryDuration with get, set
member val MergeMode = MergeFragmentsOptions.defaults.MergeMode with get, set
member val Selector = "" with get, set
member val SettleDuration = MergeFragmentsOptions.defaults.SettleDuration with get, set
member val UseViewTransition = MergeFragmentsOptions.defaults.UseViewTransition with get, set
member internal this.AsOptions : MergeFragmentsOptions =
{ Selector = this.Selector |> ValueOption.fromEmptyString
MergeMode = this.MergeMode
SettleDuration = this.SettleDuration
UseViewTransition = this.UseViewTransition
EventId = this.EventId |> ValueOption.fromEmptyString
Retry = this.Retry }
@ -97,11 +95,9 @@ and ServerSentEventMergeSignalsOptions() =
and ServerSentEventRemoveFragmentsOptions() =
member val EventId = "" with get, set
member val Retry = Consts.DefaultSseRetryDuration with get, set
member val SettleDuration = MergeFragmentsOptions.defaults.SettleDuration with get, set
member val UseViewTransition = MergeFragmentsOptions.defaults.UseViewTransition with get, set
member internal this.AsOptions : RemoveFragmentsOptions =
{ SettleDuration = this.SettleDuration
UseViewTransition = this.UseViewTransition
{ UseViewTransition = this.UseViewTransition
EventId = this.EventId |> ValueOption.fromEmptyString
Retry = this.Retry }

View File

@ -17,7 +17,6 @@ type ServerSentEventGenerator =
DataLines = [|
if (options.Selector |> ValueOption.isSome) then $"{Consts.DatastarDatalineSelector} {options.Selector |> ValueOption.get |> Selector.value}"
if (options.MergeMode <> Consts.DefaultFragmentMergeMode) then $"{Consts.DatastarDatalineMergeMode} {options.MergeMode |> Consts.FragmentMergeMode.toString}"
if (options.SettleDuration <> Consts.DefaultFragmentsSettleDuration) then $"{Consts.DatastarDatalineSettleDuration} {options.SettleDuration.Milliseconds}"
if (options.UseViewTransition <> Consts.DefaultFragmentsUseViewTransitions) then $"{Consts.DatastarDatalineUseViewTransition} %A{options.UseViewTransition}"
yield! (fragments |> String.split String.newLines |> Seq.map (fun fragmentLine -> $"{Consts.DatastarDatalineFragments} %s{fragmentLine}"))
|] }
@ -30,7 +29,6 @@ type ServerSentEventGenerator =
Retry = options.Retry
DataLines = [|
$"{Consts.DatastarDatalineSelector} {selector |> Selector.value}"
if (options.SettleDuration <> Consts.DefaultFragmentsSettleDuration) then $"{Consts.DatastarDatalineSettleDuration} {options.SettleDuration.Milliseconds}"
if (options.UseViewTransition <> Consts.DefaultFragmentsUseViewTransitions) then $"{Consts.DatastarDatalineUseViewTransition} %A{options.UseViewTransition}"
|] }
|> ServerSentEventGenerator.send sseHandler

View File

@ -32,7 +32,6 @@ type Selector = string
type MergeFragmentsOptions =
{ Selector: Selector voption
MergeMode: FragmentMergeMode
SettleDuration: TimeSpan
UseViewTransition: bool
EventId: string voption
Retry: TimeSpan }
@ -41,8 +40,7 @@ type MergeSignalsOptions =
EventId: string voption
Retry: TimeSpan }
type RemoveFragmentsOptions =
{ SettleDuration: TimeSpan
UseViewTransition: bool
{ UseViewTransition: bool
EventId: string voption
Retry: TimeSpan }
type ExecuteScriptOptions =
@ -133,7 +131,6 @@ module MergeFragmentsOptions =
let defaults =
{ Selector = ValueNone
MergeMode = Consts.DefaultFragmentMergeMode
SettleDuration = Consts.DefaultFragmentsSettleDuration
UseViewTransition = Consts.DefaultFragmentsUseViewTransitions
EventId = ValueNone
Retry = Consts.DefaultSseRetryDuration }
@ -146,8 +143,7 @@ module MergeSignalsOptions =
module RemoveFragmentsOptions =
let defaults =
{ SettleDuration = Consts.DefaultFragmentsSettleDuration
UseViewTransition = Consts.DefaultFragmentsUseViewTransitions
{ UseViewTransition = Consts.DefaultFragmentsUseViewTransitions
EventId = ValueNone
Retry = Consts.DefaultSseRetryDuration }

7
sdk/go/consts.go generated
View File

@ -7,13 +7,11 @@ import "time"
const (
DatastarKey = "datastar"
Version = "1.0.0-beta.9"
VersionClientByteSize = 40074
VersionClientByteSizeGzip = 14973
VersionClientByteSize = 39670
VersionClientByteSizeGzip = 14828
//region Default durations
// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
DefaultFragmentsSettleDuration = 300 * time.Millisecond
// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
DefaultSseRetryDuration = 1000 * time.Millisecond
@ -29,7 +27,6 @@ const (
//region Dataline literals
SelectorDatalineLiteral = "selector "
MergeModeDatalineLiteral = "mergeMode "
SettleDurationDatalineLiteral = "settleDuration "
FragmentsDatalineLiteral = "fragments "
UseViewTransitionDatalineLiteral = "useViewTransition "
SignalsDatalineLiteral = "signals "

View File

@ -12,7 +12,6 @@ type MergeFragmentOptions struct {
RetryDuration time.Duration
Selector string
MergeMode FragmentMergeMode
SettleDuration time.Duration
UseViewTransitions bool
}
@ -35,12 +34,6 @@ func WithMergeMode(merge FragmentMergeMode) MergeFragmentOption {
}
}
func WithSettleDuration(d time.Duration) MergeFragmentOption {
return func(o *MergeFragmentOptions) {
o.SettleDuration = d
}
}
func WithUseViewTransitions(useViewTransition bool) MergeFragmentOption {
return func(o *MergeFragmentOptions) {
o.UseViewTransitions = useViewTransition
@ -53,7 +46,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
RetryDuration: DefaultSseRetryDuration,
Selector: "",
MergeMode: FragmentMergeModeMorph,
SettleDuration: DefaultFragmentsSettleDuration,
}
for _, opt := range opts {
opt(options)
@ -74,10 +66,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
if options.MergeMode != FragmentMergeModeMorph {
dataRows = append(dataRows, MergeModeDatalineLiteral+string(options.MergeMode))
}
if options.SettleDuration >= 0 && options.SettleDuration != DefaultFragmentsSettleDuration {
settleDuration := strconv.Itoa(int(options.SettleDuration.Milliseconds()))
dataRows = append(dataRows, SettleDurationDatalineLiteral+settleDuration)
}
if options.UseViewTransitions {
dataRows = append(dataRows, UseViewTransitionDatalineLiteral+"true")
}
@ -103,7 +91,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
type RemoveFragmentsOptions struct {
EventID string
RetryDuration time.Duration
SettleDuration time.Duration
UseViewTransitions *bool
}
@ -121,12 +108,6 @@ func WithRemoveRetryDuration(d time.Duration) RemoveFragmentsOption {
}
}
func WithRemoveSettleDuration(d time.Duration) RemoveFragmentsOption {
return func(o *RemoveFragmentsOptions) {
o.SettleDuration = d
}
}
func WithRemoveUseViewTransitions(useViewTransition bool) RemoveFragmentsOption {
return func(o *RemoveFragmentsOptions) {
o.UseViewTransitions = &useViewTransition
@ -141,7 +122,6 @@ func (sse *ServerSentEventGenerator) RemoveFragments(selector string, opts ...Re
options := &RemoveFragmentsOptions{
EventID: "",
RetryDuration: DefaultSseRetryDuration,
SettleDuration: DefaultFragmentsSettleDuration,
UseViewTransitions: nil,
}
for _, opt := range opts {
@ -149,10 +129,6 @@ func (sse *ServerSentEventGenerator) RemoveFragments(selector string, opts ...Re
}
dataRows := []string{SelectorDatalineLiteral + selector}
if options.SettleDuration >= 0 && options.SettleDuration != DefaultFragmentsSettleDuration {
settleDuration := strconv.Itoa(int(options.SettleDuration.Milliseconds()))
dataRows = append(dataRows, SettleDurationDatalineLiteral+settleDuration)
}
if options.UseViewTransitions != nil {
dataRows = append(dataRows, UseViewTransitionDatalineLiteral+strconv.FormatBool(*options.UseViewTransitions))
}

View File

@ -115,7 +115,6 @@ data: fragments line 2
event: datastar-merge-fragments
data: selector #id
data: mergeMode inner
data: settleDuration 1
data: fragments line 1
data: fragments line 2
<BLANKLINE>
@ -124,7 +123,6 @@ id: abc123
retry: 10
data: selector #id
data: mergeMode inner
data: settleDuration 1
data: useViewTransition true
data: fragments line 1
data: fragments line 2
@ -157,18 +155,15 @@ data: selector #id
<BLANKLINE>
event: datastar-remove-fragments
data: selector #id
data: settleDuration 1
<BLANKLINE>
event: datastar-remove-fragments
data: selector #id
data: settleDuration 1
data: useViewTransition true
<BLANKLINE>
event: datastar-remove-fragments
id: abc123
retry: 10
data: selector #id
data: settleDuration 1
<BLANKLINE>
-}

View File

@ -19,8 +19,6 @@ cVersionClientByteSize :: Int
cVersionClientByteSize = 36872
cVersionClientByteSizeGzip :: Int
cVersionClientByteSizeGzip = 13691
cDefaultFragmentsSettleDuration :: Int
cDefaultFragmentsSettleDuration = 300 -- milliseconds
cDefaultSseRetryDuration :: Int
cDefaultSseRetryDuration = 1000 -- milliseconds
cExecuteScriptAttributes :: StringLike a => a
@ -29,8 +27,6 @@ cSelector :: StringLike a => a
cSelector = "selector"
cMergeMode :: StringLike a => a
cMergeMode = "mergeMode"
cSettleDuration :: StringLike a => a
cSettleDuration = "settleDuration"
cFragments :: StringLike a => a
cFragments = "fragments"
cUseViewTransition :: StringLike a => a

View File

@ -101,7 +101,6 @@ instance Prompt MergeMode where
prompt UpsertAttributes = cUpsertAttributes
data FragmentOptions = FO {
settleDuration :: Int
, useViewTransition :: Bool
} deriving (Show)
@ -109,13 +108,11 @@ data FragmentOptions = FO {
instance Default FragmentOptions where
def = FO {
settleDuration = cDefaultFragmentsSettleDuration
, useViewTransition = cDefaultFragmentsUseViewTransitions
useViewTransition = cDefaultFragmentsUseViewTransitions
}
instance Prompt FragmentOptions where
prompt (FO a b) = mconcat . buildLines $ [
withDefault cSettleDuration (prompt cDefaultFragmentsSettleDuration) (prompt a)
, withDefault cUseViewTransition (prompt cDefaultFragmentsUseViewTransitions) (prompt b)
]

View File

@ -91,7 +91,7 @@ handlerFeed = do
threadDelay (1 * 1000 * 1000)
writeBoth x w = putStrLn (T.unpack x) >> sendInApp (feedDstar x) w
sleeping = "Sleeping for 70 seconds, but continuing to ping"
allDone = "All Done, the settleDuration to remove the div is 5 seconds"
allDone = "All Done"
feedDstar :: Text -> Text
feedDstar x = mergeFragments ("<div id=\"feed\"><b>" <> x <> "</b></div>") def def def def
removeDstar :: Text

View File

@ -30,7 +30,6 @@
<br/>the pings will continue so we don't time out. Then we will again
<br/>replace the div with the current time 10 times. After that this
<br/>text will be removed with a RemoveFragments command
<br/>after a "settleDuration" of 5 seconds
</div>
<br/>
<div id="feed"><b>feed goes here</b></div>

View File

@ -91,14 +91,12 @@ This event is used to merge fragments into the DOM. The data is a string that re
- `selector` (string) The CSS selector to use to insert the fragments. If not provided or empty, Datastar **will** default to using the `id` attribute of the fragment.
- `mergeMode` (FragmentMergeMode) The mode to use when merging the fragment into the DOM. If not provided the Datastar client side **_will_** default to `morph`.
- `settleDuration` is used to control the amount of time that a fragment should take before removing any CSS related to settling. It is used to allow for animations in the browser via the Datastar client. If provided the value **_must_** be a positive integer of the number of milliseconds to allow for settling. If none is provided, the default value of `300` milliseconds will be used.
- `useViewTransition` Whether to use view transitions, if not provided the Datastar client side **_will_** default to `false`.
```java
MergeFragments event = MergeFragments.builder()
.selector("#feed")
.mergeMode(FragmentMergeMode.Append)
.settleDuration(500)
.useViewTransition(true)
.data("<div id=\"feed\">\n<span>1</span>\n</div>")
.build();
@ -111,13 +109,11 @@ This event is used to remove fragments from the DOM.
##### Options
- `selector` (string) The CSS selector to use to insert the fragments. If not provided or empty, Datastar **will** default to using the `id` attribute of the fragment.
- `settleDuration` is used to control the amount of time that a fragment should take before removing any CSS related to settling. It is used to allow for animations in the browser via the Datastar client. If provided the value **_must_** be a positive integer of the number of milliseconds to allow for settling. If none is provided, the default value of `300` milliseconds will be used.
- `useViewTransition` Whether to use view transitions, if not provided the Datastar client side **_will_** default to `false`.
```java
RemoveFragments event = RemoveFragments.builder()
.selector("#feed")
.settleDuration(500)
.useViewTransition(true)
.build();
```

View File

@ -9,9 +9,6 @@ public final class Consts {
public static final String DATASTAR_KEY = "datastar";
public static final String VERSION = "1.0.0-beta.9";
// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
public static final int DEFAULT_FRAGMENTS_SETTLE_DURATION = 300;
// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
public static final int DEFAULT_SSE_RETRY_DURATION = 1000;
@ -33,7 +30,6 @@ public final class Consts {
// Dataline literals.
public static final String SELECTOR_DATALINE_LITERAL = "selector ";
public static final String MERGE_MODE_DATALINE_LITERAL = "mergeMode ";
public static final String SETTLE_DURATION_DATALINE_LITERAL = "settleDuration ";
public static final String FRAGMENTS_DATALINE_LITERAL = "fragments ";
public static final String USE_VIEW_TRANSITION_DATALINE_LITERAL = "useViewTransition ";
public static final String SIGNALS_DATALINE_LITERAL = "signals ";

View File

@ -28,7 +28,6 @@ public final class MergeFragments extends AbstractDatastarEvent {
public static final class Builder extends AbstractBuilder<MergeFragments> {
private String selector;
private FragmentMergeMode mergeMode = DEFAULT_FRAGMENT_MERGE_MODE; // Default
private int settleDuration = DEFAULT_FRAGMENTS_SETTLE_DURATION; // Default
private boolean useViewTransition = DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; // Default
private String rawData;
@ -45,11 +44,6 @@ public final class MergeFragments extends AbstractDatastarEvent {
return this;
}
public Builder settleDuration(int settleDuration) {
this.settleDuration = settleDuration;
return this;
}
public Builder useViewTransition(boolean useViewTransition) {
this.useViewTransition = useViewTransition;
return this;
@ -78,11 +72,6 @@ public final class MergeFragments extends AbstractDatastarEvent {
dataLines.add(MERGE_MODE_DATALINE_LITERAL + mergeMode);
}
// Add settleDuration if not default
if (settleDuration != DEFAULT_FRAGMENTS_SETTLE_DURATION) {
dataLines.add(SETTLE_DURATION_DATALINE_LITERAL + settleDuration);
}
// Add useViewTransition if true
if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
dataLines.add(USE_VIEW_TRANSITION_DATALINE_LITERAL + useViewTransition);

View File

@ -25,7 +25,6 @@ public final class RemoveFragments extends AbstractDatastarEvent {
public static final class Builder extends AbstractBuilder<RemoveFragments> {
private String selector;
private int settleDuration = DEFAULT_FRAGMENTS_SETTLE_DURATION; // Default
private boolean useViewTransition = DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; // Default
private Builder() {
}
@ -34,11 +33,6 @@ public final class RemoveFragments extends AbstractDatastarEvent {
return this;
}
public Builder settleDuration(int settleDuration) {
this.settleDuration = settleDuration;
return this;
}
public Builder useViewTransition(boolean useViewTransition) {
this.useViewTransition = useViewTransition;
return this;
@ -55,11 +49,6 @@ public final class RemoveFragments extends AbstractDatastarEvent {
// Add selector
dataLines.add(SELECTOR_DATALINE_LITERAL + selector.trim());
// Add settleDuration if not default
if (settleDuration != DEFAULT_FRAGMENTS_SETTLE_DURATION) {
dataLines.add(SETTLE_DURATION_DATALINE_LITERAL + settleDuration);
}
// Add useViewTransition if true
if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
dataLines.add(USE_VIEW_TRANSITION_DATALINE_LITERAL + useViewTransition);

View File

@ -14,7 +14,6 @@ class MergeFragmentsTest {
MergeFragments event = MergeFragments.builder()
.selector("#feed")
.mergeMode(FragmentMergeMode.Append)
.settleDuration(500)
.useViewTransition(true)
.data("<div id=\"feed\">\n<span>1</span>\n</div>")
.build();
@ -22,7 +21,6 @@ class MergeFragmentsTest {
String[] expectedDataLines = {
"selector #feed",
"mergeMode append",
"settleDuration 500",
"useViewTransition true",
"fragments <div id=\"feed\">",
"fragments <span>1</span>",

View File

@ -12,13 +12,11 @@ class RemoveFragmentsTest {
void builderShouldGenerateCorrectEvent() {
RemoveFragments event = RemoveFragments.builder()
.selector("#feed")
.settleDuration(500)
.useViewTransition(true)
.build();
String[] expectedDataLines = {
"selector #feed",
"settleDuration 500",
"useViewTransition true"
};

View File

@ -39,7 +39,6 @@ $sse = new ServerSentEventGenerator();
$sse->mergeFragments('<div></div>', [
'selector' => '#my-div',
'mergeMode' => FragmentMergeMode::Append,
'settleDuration' => 1000,
'useViewTransition' => true,
]);

View File

@ -1,7 +1,6 @@
{
"name": "starfederation/datastar-php",
"description": "A PHP SDK for working with Datastar.",
"version": "1.0.0-beta.16",
"type": "library",
"license": "mit",
"require": {

View File

@ -12,9 +12,6 @@ class Consts
public const DATASTAR_KEY = 'datastar';
public const VERSION = '1.0.0-beta.9';
// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
public const DEFAULT_FRAGMENTS_SETTLE_DURATION = 300;
// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
public const DEFAULT_SSE_RETRY_DURATION = 1000;
@ -36,7 +33,6 @@ class Consts
// Dataline literals.
public const SELECTOR_DATALINE_LITERAL = 'selector ';
public const MERGE_MODE_DATALINE_LITERAL = 'mergeMode ';
public const SETTLE_DURATION_DATALINE_LITERAL = 'settleDuration ';
public const FRAGMENTS_DATALINE_LITERAL = 'fragments ';
public const USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition ';
public const SIGNALS_DATALINE_LITERAL = 'signals ';

View File

@ -69,7 +69,6 @@ class ServerSentEventGenerator
* @param array{
* selector?: string|null,
* mergeMode?: FragmentMergeMode|string|null,
* settleDuration?: int|null,
* useViewTransition?: bool|null,
* eventId?: string|null,
* retryDuration?: int|null,

View File

@ -17,7 +17,6 @@ class MergeFragments implements EventInterface
public string $fragments;
public string $selector = '';
public FragmentMergeMode $mergeMode = Consts::DEFAULT_FRAGMENT_MERGE_MODE;
public int $settleDuration = Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION;
public bool $useViewTransition = Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS;
public function __construct(string $fragments, array $options = [])
@ -56,10 +55,6 @@ class MergeFragments implements EventInterface
$dataLines[] = $this->getDataLine(Consts::MERGE_MODE_DATALINE_LITERAL, $this->mergeMode->value);
}
if ($this->settleDuration != Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION) {
$dataLines[] = $this->getDataLine(Consts::SETTLE_DURATION_DATALINE_LITERAL, $this->settleDuration);
}
if ($this->useViewTransition !== Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
$dataLines[] = $this->getDataLine(Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL, $this->getBooleanAsString($this->useViewTransition));
}

View File

@ -13,7 +13,6 @@ class RemoveFragments implements EventInterface
use EventTrait;
public string $selector;
public int $settleDuration = Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION;
public bool $useViewTransition = Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS;
public function __construct(string $selector, array $options = [])
@ -42,10 +41,6 @@ class RemoveFragments implements EventInterface
$this->getDataLine(Consts::SELECTOR_DATALINE_LITERAL, $this->selector),
];
if ($this->settleDuration !== Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION) {
$dataLines[] = $this->getDataLine(Consts::SETTLE_DURATION_DATALINE_LITERAL, $this->settleDuration);
}
if ($this->useViewTransition !== Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
$dataLines[] = $this->getDataLine(Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL, $this->getBooleanAsString($this->useViewTransition));
}

View File

@ -24,14 +24,12 @@ test('Options are correctly output', function() {
$event = new MergeFragments($content, [
'selector' => 'selector',
'mergeMode' => FragmentMergeMode::Append,
'settleDuration' => 1000,
'useViewTransition' => true,
]);
expect($event->getDataLines())
->toBe([
'data: selector selector',
'data: mergeMode append',
'data: settleDuration 1000',
'data: useViewTransition true',
'data: fragments ' . $content,
]);
@ -42,7 +40,6 @@ test('Default options are not output', function() {
$event = new MergeFragments($content, [
'selector' => '',
'mergeMode' => FragmentMergeMode::Morph,
'settleDuration' => Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION,
'useViewTransition' => false,
]);
expect($event->getDataLines())

View File

@ -6,13 +6,11 @@ use starfederation\datastar\events\RemoveFragments;
test('Options are correctly output', function() {
$content = 'body';
$event = new RemoveFragments($content, [
'settleDuration' => 1000,
'useViewTransition' => true,
]);
expect($event->getDataLines())
->toBe([
'data: selector body',
'data: settleDuration 1000',
'data: useViewTransition true',
]);
});
@ -20,7 +18,6 @@ test('Options are correctly output', function() {
test('Default options are not output', function() {
$content = 'body';
$event = new RemoveFragments($content, [
'settleDuration' => Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION,
'useViewTransition' => false,
]);
expect($event->getDataLines())

View File

@ -55,8 +55,6 @@ VERSION = "1.0.0-beta.9"
#region Default durations
# The default duration for settling during fragment merges. Allows for CSS transitions to complete.
DefaultFragmentsSettleDuration = 300
# The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
DefaultSseRetryDuration = 1000
@ -72,7 +70,6 @@ DefaultExecuteScriptAttributes = "type module"
#region Dataline literals
SelectorDatalineLiteral = "selector"
MergeModeDatalineLiteral = "mergeMode"
SettleDurationDatalineLiteral = "settleDuration"
FragmentsDatalineLiteral = "fragments"
UseViewTransitionDatalineLiteral = "useViewTransition"
SignalsDatalineLiteral = "signals"

View File

@ -41,7 +41,6 @@ class ServerSentEventGenerator:
fragments: list[str],
selector: Optional[str] = None,
merge_mode: Optional[consts.FragmentMergeMode] = None,
settle_duration: Optional[int] = None,
use_view_transition: bool = consts.DefaultFragmentsUseViewTransitions,
event_id: Optional[int] = None,
retry_duration: int = consts.DefaultSseRetryDuration,
@ -55,10 +54,6 @@ class ServerSentEventGenerator:
data_lines.append(f"data: {consts.UseViewTransitionDatalineLiteral} true")
else:
data_lines.append(f"data: {consts.UseViewTransitionDatalineLiteral} false")
if settle_duration:
data_lines.append(
f"data: {consts.SettleDurationDatalineLiteral} {settle_duration}"
)
data_lines.extend(
f"data: {consts.FragmentsDatalineLiteral} {x}"
@ -77,7 +72,6 @@ class ServerSentEventGenerator:
def remove_fragments(
cls,
selector: Optional[str] = None,
settle_duration: Optional[int] = None,
use_view_transition: bool = True,
event_id: Optional[int] = None,
retry_duration: int = consts.DefaultSseRetryDuration,
@ -89,10 +83,6 @@ class ServerSentEventGenerator:
data_lines.append(f"data: {consts.UseViewTransitionDatalineLiteral} true")
else:
data_lines.append(f"data: {consts.UseViewTransitionDatalineLiteral} false")
if settle_duration:
data_lines.append(
f"data: {consts.SettleDurationDatalineLiteral} {settle_duration}"
)
return ServerSentEventGenerator._send(
consts.EventType.EventTypeRemoveFragments,

View File

@ -6,9 +6,6 @@ module Datastar
DATASTAR_KEY = 'datastar'
VERSION = '1.0.0-beta.9'
# The default duration for settling during fragment merges. Allows for CSS transitions to complete.
DEFAULT_FRAGMENTS_SETTLE_DURATION = 300
# The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
DEFAULT_SSE_RETRY_DURATION = 1000
@ -57,7 +54,6 @@ module Datastar
# Dataline literals.
SELECTOR_DATALINE_LITERAL = 'selector'
MERGE_MODE_DATALINE_LITERAL = 'mergeMode'
SETTLE_DURATION_DATALINE_LITERAL = 'settleDuration'
FRAGMENTS_DATALINE_LITERAL = 'fragments'
USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition'
SIGNALS_DATALINE_LITERAL = 'signals'

View File

@ -17,7 +17,6 @@ module Datastar
'retry' => Consts::DEFAULT_SSE_RETRY_DURATION,
Consts::AUTO_REMOVE_DATALINE_LITERAL => Consts::DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE,
Consts::MERGE_MODE_DATALINE_LITERAL => Consts::DEFAULT_FRAGMENT_MERGE_MODE,
Consts::SETTLE_DURATION_DATALINE_LITERAL => Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION,
Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL => Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
Consts::ONLY_IF_MISSING_DATALINE_LITERAL => Consts::DEFAULT_MERGE_SIGNALS_ONLY_IF_MISSING,
}.freeze

View File

@ -75,26 +75,24 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments(
%(<div id="foo">\n<span>hello</span>\n</div>\n),
id: 72,
retry_duration: 2000,
settle_duration: 1000
retry_duration: 2000
)
socket = TestSocket.new
dispatcher.response.body.call(socket)
expect(socket.open).to be(false)
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: settleDuration 1000\ndata: fragments <div id="foo">\ndata: fragments <span>hello</span>\ndata: fragments </div>\n\n\n)])
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: fragments <div id="foo">\ndata: fragments <span>hello</span>\ndata: fragments </div>\n\n\n)])
end
it 'omits retry if using default value' do
dispatcher.merge_fragments(
%(<div id="foo">\n<span>hello</span>\n</div>\n),
id: 72,
retry_duration: 1000,
settle_duration: 1000
retry_duration: 1000
)
socket = TestSocket.new
dispatcher.response.body.call(socket)
expect(socket.open).to be(false)
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\ndata: settleDuration 1000\ndata: fragments <div id="foo">\ndata: fragments <span>hello</span>\ndata: fragments </div>\n\n\n)])
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\ndata: fragments <div id="foo">\ndata: fragments <span>hello</span>\ndata: fragments </div>\n\n\n)])
end
it 'works with #call(view_context:) interfaces' do
@ -105,12 +103,11 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments(
template_class,
id: 72,
retry_duration: 2000,
settle_duration: 1000
retry_duration: 2000
)
socket = TestSocket.new
dispatcher.response.body.call(socket)
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: settleDuration 1000\ndata: fragments <div id="foo">\ndata: fragments <span>#{view_context}</span>\ndata: fragments </div>\n\n\n)])
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: fragments <div id="foo">\ndata: fragments <span>#{view_context}</span>\ndata: fragments </div>\n\n\n)])
end
it 'works with #render_in(view_context, &) interfaces' do
@ -121,12 +118,11 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments(
template_class,
id: 72,
retry_duration: 2000,
settle_duration: 1000
retry_duration: 2000
)
socket = TestSocket.new
dispatcher.response.body.call(socket)
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: settleDuration 1000\ndata: fragments <div id="foo">\ndata: fragments <span>#{view_context}</span>\ndata: fragments </div>\n\n\n)])
expect(socket.lines).to eq([%(event: datastar-merge-fragments\nid: 72\nretry: 2000\ndata: fragments <div id="foo">\ndata: fragments <span>#{view_context}</span>\ndata: fragments </div>\n\n\n)])
end
end
@ -140,11 +136,11 @@ RSpec.describe Datastar::Dispatcher do
end
it 'takes D* options' do
dispatcher.remove_fragments('#list-item-1', id: 72, settle_duration: 1000)
dispatcher.remove_fragments('#list-item-1', id: 72)
socket = TestSocket.new
dispatcher.response.body.call(socket)
expect(socket.open).to be(false)
expect(socket.lines).to eq([%(event: datastar-remove-fragments\nid: 72\ndata: settleDuration 1000\ndata: selector #list-item-1\n\n\n)])
expect(socket.lines).to eq([%(event: datastar-remove-fragments\nid: 72\ndata: selector #list-item-1\n\n\n)])
end
end

View File

@ -7,8 +7,6 @@ pub const _VERSION: &str = "1.0.0-beta.9";
// #region Default durations
/// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
pub const DEFAULT_FRAGMENTS_SETTLE_DURATION: u64 = 300;
/// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
pub const DEFAULT_SSE_RETRY_DURATION: u64 = 1000;
@ -25,7 +23,6 @@ pub const DEFAULT_EXECUTE_SCRIPT_ATTRIBUTES: &str = "type module";
pub const SELECTOR_DATALINE_LITERAL: &str = "selector";
pub const MERGE_MODE_DATALINE_LITERAL: &str = "mergeMode";
pub const SETTLE_DURATION_DATALINE_LITERAL: &str = "settleDuration";
pub const FRAGMENTS_DATALINE_LITERAL: &str = "fragments";
pub const USE_VIEW_TRANSITION_DATALINE_LITERAL: &str = "useViewTransition";
pub const SIGNALS_DATALINE_LITERAL: &str = "signals";

View File

@ -25,7 +25,6 @@ use {
/// yield MergeFragments::new("<h1>Hello, world!</h1>")
/// .selector("body")
/// .merge_mode(FragmentMergeMode::Append)
/// .settle_duration(Duration::from_millis(1000))
/// .use_view_transition(true)
/// .into();
/// });
@ -47,9 +46,6 @@ pub struct MergeFragments {
/// The mode to use when merging the fragment into the DOM.
/// If not provided the Datastar client side will default to [`FragmentMergeMode::Morph`].
pub merge_mode: FragmentMergeMode,
/// The amount of time that a fragment should take before removing any CSS related to settling.
/// `settle_duration` is used to allow for animations in the browser via the Datastar client.
pub settle_duration: Duration,
/// Whether to use view transitions, if not provided the Datastar client side will default to `false`.
pub use_view_transition: bool,
}
@ -63,7 +59,6 @@ impl MergeFragments {
fragments: fragments.into(),
selector: None,
merge_mode: FragmentMergeMode::default(),
settle_duration: Duration::from_millis(consts::DEFAULT_FRAGMENTS_SETTLE_DURATION),
use_view_transition: consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
}
}
@ -92,12 +87,6 @@ impl MergeFragments {
self
}
/// Sets the `settle_duration` of the [`MergeFragments`] event.
pub fn settle_duration(mut self, settle_duration: Duration) -> Self {
self.settle_duration = settle_duration;
self
}
/// Sets the `use_view_transition` of the [`MergeFragments`] event.
pub fn use_view_transition(mut self, use_view_transition: bool) -> Self {
self.use_view_transition = use_view_transition;
@ -125,14 +114,6 @@ impl From<MergeFragments> for DatastarEvent {
));
}
if val.settle_duration.as_millis() != consts::DEFAULT_FRAGMENTS_SETTLE_DURATION as u128 {
data.push(format!(
"{} {}",
consts::SETTLE_DURATION_DATALINE_LITERAL,
val.settle_duration.as_millis()
));
}
if val.use_view_transition != consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS {
data.push(format!(
"{} {}",

View File

@ -18,7 +18,6 @@ use {
///
/// Sse(stream! {
/// yield RemoveFragments::new("#foo")
/// .settle_duration(Duration::from_millis(1000))
/// .use_view_transition(true)
/// .into();
/// });
@ -36,9 +35,6 @@ pub struct RemoveFragments {
/// The selector must be a valid CSS selector.
/// The Datastar client side will use this selector to remove the fragment from the DOM.
pub selector: String,
/// The amount of time that a fragment should take before removing any CSS related to settling.
/// `settle_duration` is used to allow for animations in the browser via the Datastar client.
pub settle_duration: Duration,
/// Whether to use view transitions, if not provided the Datastar client side will default to `false`.
pub use_view_transition: bool,
}
@ -50,7 +46,6 @@ impl RemoveFragments {
id: None,
retry: Duration::from_millis(consts::DEFAULT_SSE_RETRY_DURATION),
selector: selector.into(),
settle_duration: Duration::from_millis(consts::DEFAULT_FRAGMENTS_SETTLE_DURATION),
use_view_transition: consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
}
}
@ -67,12 +62,6 @@ impl RemoveFragments {
self
}
/// Sets the `settle_duration` of the [`RemoveFragments`] event.
pub fn settle_duration(mut self, settle_duration: Duration) -> Self {
self.settle_duration = settle_duration;
self
}
/// Sets the `use_view_transition` of the [`RemoveFragments`] event.
pub fn use_view_transition(mut self, use_view_transition: bool) -> Self {
self.use_view_transition = use_view_transition;
@ -84,14 +73,6 @@ impl From<RemoveFragments> for DatastarEvent {
fn from(val: RemoveFragments) -> Self {
let mut data: Vec<String> = Vec::new();
if val.settle_duration.as_millis() != consts::DEFAULT_FRAGMENTS_SETTLE_DURATION as u128 {
data.push(format!(
"{} {}",
consts::SETTLE_DURATION_DATALINE_LITERAL,
val.settle_duration.as_millis()
));
}
if val.use_view_transition != consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS {
data.push(format!(
"{} {}",

View File

@ -28,7 +28,6 @@ pub enum TestEvent {
retry_duration: Option<u64>,
selector: Option<String>,
merge_mode: Option<String>,
settle_duration: Option<u64>,
use_view_transition: Option<bool>,
},
#[serde(rename_all = "camelCase")]
@ -43,7 +42,6 @@ pub enum TestEvent {
selector: String,
event_id: Option<String>,
retry_duration: Option<u64>,
settle_duration: Option<u64>,
use_view_transition: Option<bool>,
},
#[serde(rename_all = "camelCase")]
@ -97,7 +95,6 @@ pub fn test(events: Vec<TestEvent>) -> impl Stream<Item = DatastarEvent> {
retry_duration,
selector,
merge_mode,
settle_duration,
use_view_transition,
} => {
let merge_mode = merge_mode
@ -120,7 +117,6 @@ pub fn test(events: Vec<TestEvent>) -> impl Stream<Item = DatastarEvent> {
retry: Duration::from_millis(retry_duration.unwrap_or(consts::DEFAULT_SSE_RETRY_DURATION)),
selector,
merge_mode,
settle_duration: Duration::from_millis(settle_duration.unwrap_or(consts::DEFAULT_FRAGMENTS_SETTLE_DURATION)),
use_view_transition: use_view_transition.unwrap_or(consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS),
}.into()
},
@ -139,13 +135,11 @@ pub fn test(events: Vec<TestEvent>) -> impl Stream<Item = DatastarEvent> {
selector,
event_id,
retry_duration,
settle_duration,
use_view_transition,
} => RemoveFragments {
selector,
id: event_id,
retry: Duration::from_millis(retry_duration.unwrap_or(consts::DEFAULT_SSE_RETRY_DURATION)),
settle_duration: Duration::from_millis(settle_duration.unwrap_or(consts::DEFAULT_FRAGMENTS_SETTLE_DURATION)),
use_view_transition: use_view_transition.unwrap_or(consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS),
}.into(),
TestEvent::RemoveSignals {

View File

@ -7,7 +7,6 @@
"retryDuration": 2000,
"selector": "div",
"mergeMode": "append",
"settleDuration": 1000,
"useViewTransition": true
}
]

View File

@ -3,7 +3,6 @@ id: event1
retry: 2000
data: selector div
data: mergeMode append
data: settleDuration 1000
data: useViewTransition true
data: fragments <div>Merge</div>

View File

@ -4,7 +4,6 @@
"type": "mergeFragments",
"fragments": "<div>Merge</div>",
"mergeMode": "morph",
"settleDuration": 300,
"useViewTransition": false
}
]

View File

@ -5,7 +5,6 @@
"selector": "#target",
"eventId": "event1",
"retryDuration": 2000,
"settleDuration": 1000,
"useViewTransition": true
}
]

View File

@ -1,7 +1,6 @@
event: datastar-remove-fragments
id: event1
retry: 2000
data: settleDuration 1000
data: useViewTransition true
data: selector #target

View File

@ -3,7 +3,6 @@
{
"type": "removeFragments",
"selector": "#target",
"settleDuration": 300,
"useViewTransition": false
}
]

View File

@ -8,8 +8,6 @@ export const VERSION = "1.0.0-beta.9";
// #region Default durations
// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
export const DefaultFragmentsSettleDurationMs = 300;
// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
export const DefaultSseRetryDurationMs = 1000;
@ -41,7 +39,6 @@ export const DefaultExecuteScriptAutoRemove = true;
export const DatastarDatalineSelector = "selector"
export const DatastarDatalineMergeMode = "mergeMode"
export const DatastarDatalineSettleDuration = "settleDuration"
export const DatastarDatalineFragments = "fragments"
export const DatastarDatalineUseViewTransition = "useViewTransition"
export const DatastarDatalineSignals = "signals"

View File

@ -7,13 +7,11 @@ import {
DatastarDatalinePaths,
DatastarDatalineScript,
DatastarDatalineSelector,
DatastarDatalineSettleDuration,
DatastarDatalineSignals,
DatastarDatalineUseViewTransition,
DefaultExecuteScriptAttributes,
DefaultExecuteScriptAutoRemove,
DefaultFragmentMergeMode,
DefaultFragmentsSettleDurationMs,
DefaultFragmentsUseViewTransitions,
DefaultMergeSignalsOnlyIfMissing,
EventTypes,
@ -31,7 +29,6 @@ export interface DatastarEventOptions {
export interface FragmentOptions extends DatastarEventOptions {
[DatastarDatalineUseViewTransition]?: boolean;
[DatastarDatalineSettleDuration]?: number;
}
export interface MergeFragmentsOptions extends FragmentOptions {
@ -131,7 +128,6 @@ export type DatastarEvent =
export const DefaultMapping = {
[DatastarDatalineMergeMode]: DefaultFragmentMergeMode,
[DatastarDatalineSettleDuration]: DefaultFragmentsSettleDurationMs,
[DatastarDatalineUseViewTransition]: DefaultFragmentsUseViewTransitions,
[DatastarDatalineOnlyIfMissing]: DefaultMergeSignalsOnlyIfMissing,
[DatastarDatalineAttributes]: {

View File

@ -34,9 +34,6 @@ pub const MergeFragmentsOptions = struct {
selector: ?[]const u8 = null,
/// The mode to use when merging the fragment into the DOM.
merge_mode: consts.FragmentMergeMode = consts.default_fragment_merge_mode,
/// The amount of time that a fragment should take before removing any CSS related to settling.
/// `settle_duration` is used to allow for animations in the browser via the Datastar client.
settle_duration: u32 = consts.default_fragments_settle_duration,
/// Whether to use view transitions.
use_view_transition: bool = consts.default_fragments_use_view_transitions,
};
@ -61,9 +58,6 @@ pub const RemoveFragmentsOptions = struct {
/// `retry_duration` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
retry_duration: u32 = consts.default_sse_retry_duration,
/// The amount of time that a fragment should take before removing any CSS related to settling.
/// `settle_duration` is used to allow for animations in the browser via the Datastar client.
settle_duration: u32 = consts.default_fragments_settle_duration,
/// Whether to use view transitions.
use_view_transition: bool = consts.default_fragments_use_view_transitions,
};
@ -195,15 +189,6 @@ pub fn mergeFragments(
);
}
if (options.settle_duration != consts.default_fragments_settle_duration) {
try writer.print(
consts.settle_duration_dataline_literal ++ " {d}\n",
.{
options.settle_duration,
},
);
}
if (options.use_view_transition != consts.default_fragments_use_view_transitions) {
try writer.print(
consts.use_view_transition_dataline_literal ++ " {}\n",
@ -281,15 +266,6 @@ pub fn removeFragments(
errdefer data.deinit(self.allocator);
const writer = data.writer();
if (options.settle_duration != consts.default_fragments_settle_duration) {
try writer.print(
consts.settle_duration_dataline_literal ++ " {d}\n",
.{
options.settle_duration,
},
);
}
if (options.use_view_transition != consts.default_fragments_use_view_transitions) {
try writer.print(
consts.use_view_transition_dataline_literal ++ " {}\n",

View File

@ -9,8 +9,6 @@ pub const version = "1.0.0-beta.9";
// #region Default durations
/// The default duration for settling during fragment merges. Allows for CSS transitions to complete.
pub const default_fragments_settle_duration = 300;
/// The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
pub const default_sse_retry_duration = 1000;
@ -27,7 +25,6 @@ pub const default_execute_script_attributes = "type module";
pub const selector_dataline_literal = "selector";
pub const merge_mode_dataline_literal = "mergeMode";
pub const settle_duration_dataline_literal = "settleDuration";
pub const fragments_dataline_literal = "fragments";
pub const use_view_transition_dataline_literal = "useViewTransition";
pub const signals_dataline_literal = "signals";

View File

@ -20,7 +20,6 @@ const MergeFragments = struct {
retryDuration: ?u32 = null,
selector: ?[]const u8 = null,
mergeMode: ?consts.FragmentMergeMode = null,
settleDuration: ?u32 = null,
useViewTransition: ?bool = null,
};
@ -35,7 +34,6 @@ const RemoveFragments = struct {
selector: []const u8,
eventId: ?[]const u8 = null,
retryDuration: ?u32 = null,
settleDuration: ?u32 = null,
useViewTransition: ?bool = null,
};
@ -118,7 +116,6 @@ pub fn sdk(sse: *ServerSentEventGenerator, signals: Signals) !void {
.retry_duration = ev.retryDuration orelse consts.default_sse_retry_duration,
.selector = ev.selector,
.merge_mode = ev.mergeMode orelse consts.default_fragment_merge_mode,
.settle_duration = ev.settleDuration orelse consts.default_fragments_settle_duration,
.use_view_transition = ev.useViewTransition orelse consts.default_fragments_use_view_transitions,
},
);
@ -157,7 +154,6 @@ pub fn sdk(sse: *ServerSentEventGenerator, signals: Signals) !void {
.{
.event_id = ev.eventId,
.retry_duration = ev.retryDuration orelse consts.default_sse_retry_duration,
.settle_duration = ev.settleDuration orelse consts.default_fragments_settle_duration,
.use_view_transition = ev.useViewTransition orelse consts.default_fragments_use_view_transitions,
},
);

View File

@ -18,7 +18,6 @@ func setupExamplesLazyLoad(examplesRouter chi.Router) error {
time.Sleep(2 * time.Second)
datastar.NewSSE(w, r).MergeFragmentTempl(
lazyLoadGraph(),
datastar.WithSettleDuration(1*time.Second),
)
})

View File

@ -33,8 +33,7 @@ func setupHowTosLoadMore(howTosRedirect chi.Router) error {
if newOffset < max {
sse.MergeSignals([]byte(fmt.Sprintf(`{offset: %d}`, newOffset)))
} else {
// TODO: set settle duration back to `0` or remove entirely
sse.RemoveFragments(`#load-more`, datastar.WithRemoveSettleDuration(1))
sse.RemoveFragments(`#load-more`)
}
sse.MergeFragments(fmt.Sprintf(`<div class="text-primary font-bold">Item %d</div>`, newOffset),

View File

@ -12,7 +12,6 @@ This means every data fragment is an OOB in HTMX terms.
event: datastar-merge-fragments
id: 92680296792588350
data: mergeMode morph
data: settleDuration 0
data: fragment
<div id="lazy_tabs">
<div class="tabs tabs-bordered">

View File

@ -52,7 +52,7 @@ This button swap is happening in the backend. Each click is causing a transitio
If you want to fade out an element that is going to be removed when the request ends, just send an SSE event with the opacity set to 0 and set a transition duration. This will fade out the element before it is removed.
## Settling Transitions
## Transitions
### Fade In On Addition
@ -67,7 +67,6 @@ Building on the last example, we can fade in the new content the same way, start
One of the nice features for reactivity is to show a spinner when a request is in flight. On any element that is using backend actions you can add a `data-indicator` attribute to show a spinner when the request is in flight. This can be done like so:
```html
<div data-show="$fetching">Spinner</div>
<button
id="submit_request_in_flight"
data-on-click="@post('/examples/animations/data/request_in_flight')"
@ -75,6 +74,7 @@ One of the nice features for reactivity is to show a spinner when a request is i
>
Submit
</button>
<div data-show="$fetching">Spinner</div>
```
This will show the spinner element when the request is in flight and hide it when the request is complete.

View File

@ -4,18 +4,6 @@
## Demo
<style>
tr.deactivate.datastar-settling td {
background: lightcoral;
}
tr.activate.datastar-settling td {
background: darkseagreen;
}
tr td {
transition: all 1.2s;
}
</style>
<div
id="bulk_update"
data-on-load="@get('/examples/bulk_update/data')"
@ -26,31 +14,4 @@ transition: all 1.2s;
This demo shows how to implement a common pattern where rows are selected and then bulk updated. This is accomplished by putting a form around a table, with checkboxes in the table, and then including the checked values in PUTs to two different endpoints: `activate` and `deactivate`.
Added to the page in this way:
```html
<style>
tr.deactivate.datastar-settling td {
background: lightcoral;
}
tr.activate.datastar-settling td {
background: darkseagreen;
}
tr td {
transition: all 1.2s;
}
</style>
```
The server will either activate or deactivate the checked users and then rerender the tbody tag with updated rows. It will apply the class activate or deactivate to rows that have been mutated. This allows us to use a bit of CSS to flash a color helping the user see what happened. The server events look like this:
```go
event: datastar-merge-fragments
id: 129798448043016254
data: selector
data: mergeMode upsertAttributes
data: settleDuration 500
data: fragments ...
```
Notice the `settle` value is 500. This means the `datastar-settling` class will be added immediately and removed after 500ms. This is a nice way to show the user that something is happening.
The server will either activate or deactivate the checked users and then rerender the tbody tag with updated rows.

View File

@ -27,8 +27,7 @@ This button respond with a set of fragments in a text/event-stream with the next
```html
<!-- Removed styling for brevity -->
event: datastar-merge-fragments id: 129804115990544446 data: mergeMode morph data:
settleDuration 500 data: fragment
event: datastar-merge-fragments id: 129804115990544446 data: mergeMode morph data: fragment
<button
id="more_btn"
data-on-click="$offset=20; $limit=10; @get('/examples/click_to_load/data')"
@ -37,7 +36,7 @@ settleDuration 500 data: fragment
</button>
backend.ts:201 Received event block: event: datastar-merge-fragments id:
129804153571508286 data: selector #click_to_load_rows data: mergeMode append
data: settleDuration 500 data: fragment
data: fragment
<tr id="agent_10">
<td>Agent Smith</td>
<td>void11@null.org</td>
@ -45,14 +44,14 @@ data: settleDuration 500 data: fragment
</tr>
backend.ts:201 Received event block: event: datastar-merge-fragments id:
129804153571512382 data: selector #click_to_load_rows data: mergeMode append
data: settleDuration 500 data: fragment
data: fragment
<tr id="agent_11">
<td>Agent Smith</td>
<td>void12@null.org</td>
<td class="uppercase">205381dc855b977a</td>
</tr>
backend.ts:201 Received event block: id: 129804153571516478 data: selector
#click_to_load_rows data: mergeMode append data: settleDuration 500 data: fragment
#click_to_load_rows data: mergeMode append data: fragment
<tr id="agent_12">
<td>Agent Smith</td>
<td>void13@null.org</td>

View File

@ -4,13 +4,6 @@
## Demo
<style>
tr.datastar-swapping td {
opacity: 0;
transition: opacity 1s ease-out;
}
</style>
<div
id="delete_row"
data-on-load="@get('/examples/delete_row/data')"
@ -19,8 +12,7 @@ tr.datastar-swapping td {
## Explanation
This example shows how to implement a delete button that removes a table row upon completion. First let's look at the
table body:
This example shows how to implement a delete button that removes a table row upon completion. First let's look at the table body:
```html
<table class="table">
@ -50,13 +42,4 @@ table body:
</table>
```
The row has a normal [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) to confirm the delete action. We also use the following CSS to fade out.
```css
tr.datastar-swapping td {
opacity: 0;
transition: opacity 1s ease-out;
}
```
To fade the row out before it is swapped/removed.
The row has a normal [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) to confirm the delete action.

View File

@ -23,13 +23,11 @@ This last element contains a listener which, when scrolled into view, will trigg
event: datastar-merge-fragments
data: selector #more_btn
data: mergeMode morph
data: settleDuration 500
data: fragments <div data-intersects="$offset=10;$limit=10;@get('/examples/infinite_scroll/data')" id="more_btn"><div>Loading...</div></div>
event: datastar-merge-fragments
data: selector #click_to_load_rows
data: mergeMode append
data: settleDuration 500
data: fragments <tr id=\"agent_60\"><td>Agent Smith 3c</td><td>void61@null.org</td><td class=\"uppercase\">39b02fcf39c047c5</td></tr>"
....More rows to be appended
@ -37,7 +35,7 @@ data: fragments <tr id=\"agent_60\"><td>Agent Smith 3c</td><td>void61@null.org</
## Demo
Don't scroll too far, there are consequences
Don't scroll too far, there are consequences.
<div>
<div

View File

@ -4,12 +4,6 @@
## Demo
<style>
.datastar-settling {
opacity: 0;
}
</style>
<div id="lazy_load" data-on-load="@get('/examples/lazy_load/data')">
</div>
@ -23,10 +17,4 @@ This example shows how to lazily load an element on a page. We start with an ini
</div>
```
Which shows a progress indicator as we are loading the graph. The graph is then loaded and faded gently into view via a settling CSS transition:
```css
.datastar-settling {
opacity: 0;
}
```
Which shows a progress indicator as we are loading the graph. The graph is then loaded.

View File

@ -33,7 +33,6 @@ Additional `data` lines can be added to the response to override the default beh
| `data: mergeMode before` | Inserts the fragment before the target as a sibling. |
| `data: mergeMode after` | Inserts the fragment after the target as a sibling. |
| `data: mergeMode upsertAttributes` | Merges attributes from the fragment into the target useful for updating a signals. |
| `data: settleDuration 500` | Settles the element after 500ms, useful for transitions. Defaults to `300`. |
| `data: useViewTransition true` | Whether to use view transitions when merging into the DOM. Defaults to `false`. |
| `data: fragments` | The HTML fragments to merge into the DOM. |
@ -43,7 +42,6 @@ Sample output showing all options:
event: datastar-merge-fragments
data: selector #foo
data: mergeMode append
data: settleDuration 500
data: useViewTransition true
data: fragments <div>
data: fragments Hello, world!