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 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)). - 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. 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 ```html
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.9/bundles/datastar.js"></script> <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{ 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"), Name: toolbelt.ToCasedString("sseRetryDuration"),
Description: "The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.", 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 // MergeFragments
toolbelt.ToCasedString("mergeMode"), toolbelt.ToCasedString("mergeMode"),
toolbelt.ToCasedString("settleDuration"),
toolbelt.ToCasedString("fragments"), toolbelt.ToCasedString("fragments"),
toolbelt.ToCasedString("useViewTransition"), toolbelt.ToCasedString("useViewTransition"),

View File

@ -7,7 +7,6 @@ export const DSP = lol.slice(0, 5)
export const DSS = lol.slice(4) export const DSS = lol.slice(4)
export const DATASTAR = "{%s data.DatastarKey %}"; export const DATASTAR = "{%s data.DatastarKey %}";
export const DATASTAR_EVENT = "{%s data.DatastarKey %}-event";
export const DATASTAR_REQUEST = "{%s toolbelt.Pascal( data.DatastarKey) %}-Request"; export const DATASTAR_REQUEST = "{%s toolbelt.Pascal( data.DatastarKey) %}-Request";
// #region Defaults // #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. 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 ```html
<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.0-beta.9/bundles/datastar.js"></script> <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 DSS = lol.slice(4)
export const DATASTAR = "datastar"; export const DATASTAR = "datastar";
export const DATASTAR_EVENT = "datastar-event";
export const DATASTAR_REQUEST = "Datastar-Request"; export const DATASTAR_REQUEST = "Datastar-Request";
// #region Defaults // #region Defaults
// #region Default durations // #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. // The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
export const DefaultSseRetryDurationMs = 1000; export const DefaultSseRetryDurationMs = 1000;

View File

@ -1,8 +1,6 @@
import { DATASTAR } from '../../../engine/consts' import { DATASTAR } from '../../../engine/consts'
export const DATASTAR_SSE_EVENT = `${DATASTAR}-sse` 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 STARTED = 'started'
export const FINISHED = 'finished' export const FINISHED = 'finished'
export const ERROR = 'error' export const ERROR = 'error'

View File

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

View File

@ -87,7 +87,6 @@ ServerSentEventGenerator.MergeFragments(
options?: { options?: {
selector?: string, selector?: string,
mergeMode?: FragmentMergeMode, mergeMode?: FragmentMergeMode,
settleDuration?: durationInMilliseconds,
useViewTransition?: boolean, useViewTransition?: boolean,
eventId?: string, eventId?: string,
retryDuration?: durationInMilliseconds retryDuration?: durationInMilliseconds
@ -113,7 +112,6 @@ event: datastar-merge-fragments
id: 123 id: 123
retry: 2000 retry: 2000
data: selector #feed data: selector #feed
data: settleDuration 10
data: useViewTransition true data: useViewTransition true
data: fragments <div id="feed"> data: fragments <div id="feed">
data: fragments <span>1</span> data: fragments <span>1</span>
@ -143,16 +141,14 @@ Valid values should match the [FragmentMergeMode](#FragmentMergeMode) and curren
##### Options ##### 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. * `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`. * `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`. * `useViewTransition` Whether to use view transitions, if not provided the Datastar client side ***will*** default to `false`.
#### Logic #### Logic
When called the function ***must*** call `ServerSentEventGenerator.send` with the `datastar-merge-fragments` event type. 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. 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`. 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. 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. 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.
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.
### `ServerSentEventGenerator.RemoveFragments` ### `ServerSentEventGenerator.RemoveFragments`
@ -160,7 +156,6 @@ When called the function ***must*** call `ServerSentEventGenerator.send` with th
ServerSentEventGenerator.RemoveFragments( ServerSentEventGenerator.RemoveFragments(
selector: string, selector: string,
options?: { options?: {
settleDuration?: durationInMilliseconds,
useViewTransition?: boolean, useViewTransition?: boolean,
eventId?: string, eventId?: string,
retryDuration?: durationInMilliseconds retryDuration?: durationInMilliseconds
@ -184,7 +179,6 @@ event: datastar-remove-fragments
id: 123 id: 123
retry: 2000 retry: 2000
data: selector #target data: selector #target
data: settleDuration 200
data: useViewTransition true data: useViewTransition true
``` ```
@ -196,14 +190,12 @@ data: useViewTransition true
##### Options ##### 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`. * `useViewTransition` Whether to use view transitions, if not provided the Datastar client side ***will*** default to `false`.
#### Logic #### Logic
1. When called the function ***must*** call `ServerSentEventGenerator.send` with the `datastar-remove-fragments` event type. 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`. 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. 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. 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` ### `ServerSentEventGenerator.MergeSignals`

View File

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

View File

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

View File

@ -14,7 +14,6 @@ These function take options map whose keys are:
- [[retry-duration]] - [[retry-duration]]
- [[selector]] - [[selector]]
- [[merge-mode]] - [[merge-mode]]
- [[settle-duration]]
- [[use-view-transition]] - [[use-view-transition]]
- [[only-if-missing]] - [[only-if-missing]]
- [[auto-remove]] - [[auto-remove]]
@ -155,16 +154,6 @@ Some scripts are provided:
" "
common/merge-mode) 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 (def use-view-transition
"[[merge-fragment!]] / [[remove-fragment!] option, boolean: "[[merge-fragment!]] / [[remove-fragment!] option, boolean:
@ -247,7 +236,6 @@ Some scripts are provided:
- [[retry-duration]] - [[retry-duration]]
- [[selector]] - [[selector]]
- [[merge-mode]] - [[merge-mode]]
- [[settle-duration]]
- [[use-view-transition]] - [[use-view-transition]]
Return value: Return value:
@ -282,7 +270,6 @@ Some scripts are provided:
Options keys: Options keys:
- [[id]] - [[id]]
- [[retry-duration]] - [[retry-duration]]
- [[settle-duration]]
- [[use-view-transition]] - [[use-view-transition]]
Return value: Return value:

View File

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

View File

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

View File

@ -11,10 +11,6 @@
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
;; Default durations ;; 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 (def default-sse-retry-duration
"The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE." "The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE."
1000) 1000)
@ -36,7 +32,6 @@
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
(def selector-dataline-literal "selector ") (def selector-dataline-literal "selector ")
(def merge-mode-dataline-literal "mergeMode ") (def merge-mode-dataline-literal "mergeMode ")
(def settle-duration-dataline-literal "settleDuration ")
(def fragments-dataline-literal "fragments ") (def fragments-dataline-literal "fragments ")
(def use-view-transition-dataline-literal "useViewTransition ") (def use-view-transition-dataline-literal "useViewTransition ")
(def signals-dataline-literal "signals ") (def signals-dataline-literal "signals ")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

7
sdk/go/consts.go generated
View File

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

View File

@ -12,7 +12,6 @@ type MergeFragmentOptions struct {
RetryDuration time.Duration RetryDuration time.Duration
Selector string Selector string
MergeMode FragmentMergeMode MergeMode FragmentMergeMode
SettleDuration time.Duration
UseViewTransitions bool 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 { func WithUseViewTransitions(useViewTransition bool) MergeFragmentOption {
return func(o *MergeFragmentOptions) { return func(o *MergeFragmentOptions) {
o.UseViewTransitions = useViewTransition o.UseViewTransitions = useViewTransition
@ -53,7 +46,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
RetryDuration: DefaultSseRetryDuration, RetryDuration: DefaultSseRetryDuration,
Selector: "", Selector: "",
MergeMode: FragmentMergeModeMorph, MergeMode: FragmentMergeModeMorph,
SettleDuration: DefaultFragmentsSettleDuration,
} }
for _, opt := range opts { for _, opt := range opts {
opt(options) opt(options)
@ -74,10 +66,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
if options.MergeMode != FragmentMergeModeMorph { if options.MergeMode != FragmentMergeModeMorph {
dataRows = append(dataRows, MergeModeDatalineLiteral+string(options.MergeMode)) 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 { if options.UseViewTransitions {
dataRows = append(dataRows, UseViewTransitionDatalineLiteral+"true") dataRows = append(dataRows, UseViewTransitionDatalineLiteral+"true")
} }
@ -103,7 +91,6 @@ func (sse *ServerSentEventGenerator) MergeFragments(fragment string, opts ...Mer
type RemoveFragmentsOptions struct { type RemoveFragmentsOptions struct {
EventID string EventID string
RetryDuration time.Duration RetryDuration time.Duration
SettleDuration time.Duration
UseViewTransitions *bool 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 { func WithRemoveUseViewTransitions(useViewTransition bool) RemoveFragmentsOption {
return func(o *RemoveFragmentsOptions) { return func(o *RemoveFragmentsOptions) {
o.UseViewTransitions = &useViewTransition o.UseViewTransitions = &useViewTransition
@ -141,7 +122,6 @@ func (sse *ServerSentEventGenerator) RemoveFragments(selector string, opts ...Re
options := &RemoveFragmentsOptions{ options := &RemoveFragmentsOptions{
EventID: "", EventID: "",
RetryDuration: DefaultSseRetryDuration, RetryDuration: DefaultSseRetryDuration,
SettleDuration: DefaultFragmentsSettleDuration,
UseViewTransitions: nil, UseViewTransitions: nil,
} }
for _, opt := range opts { for _, opt := range opts {
@ -149,10 +129,6 @@ func (sse *ServerSentEventGenerator) RemoveFragments(selector string, opts ...Re
} }
dataRows := []string{SelectorDatalineLiteral + selector} 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 { if options.UseViewTransitions != nil {
dataRows = append(dataRows, UseViewTransitionDatalineLiteral+strconv.FormatBool(*options.UseViewTransitions)) dataRows = append(dataRows, UseViewTransitionDatalineLiteral+strconv.FormatBool(*options.UseViewTransitions))
} }

View File

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

View File

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

View File

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

View File

@ -91,7 +91,7 @@ handlerFeed = do
threadDelay (1 * 1000 * 1000) threadDelay (1 * 1000 * 1000)
writeBoth x w = putStrLn (T.unpack x) >> sendInApp (feedDstar x) w writeBoth x w = putStrLn (T.unpack x) >> sendInApp (feedDstar x) w
sleeping = "Sleeping for 70 seconds, but continuing to ping" 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 :: Text -> Text
feedDstar x = mergeFragments ("<div id=\"feed\"><b>" <> x <> "</b></div>") def def def def feedDstar x = mergeFragments ("<div id=\"feed\"><b>" <> x <> "</b></div>") def def def def
removeDstar :: Text removeDstar :: Text

View File

@ -30,7 +30,6 @@
<br/>the pings will continue so we don't time out. Then we will again <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/>replace the div with the current time 10 times. After that this
<br/>text will be removed with a RemoveFragments command <br/>text will be removed with a RemoveFragments command
<br/>after a "settleDuration" of 5 seconds
</div> </div>
<br/> <br/>
<div id="feed"><b>feed goes here</b></div> <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. - `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`. - `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`. - `useViewTransition` Whether to use view transitions, if not provided the Datastar client side **_will_** default to `false`.
```java ```java
MergeFragments event = MergeFragments.builder() MergeFragments event = MergeFragments.builder()
.selector("#feed") .selector("#feed")
.mergeMode(FragmentMergeMode.Append) .mergeMode(FragmentMergeMode.Append)
.settleDuration(500)
.useViewTransition(true) .useViewTransition(true)
.data("<div id=\"feed\">\n<span>1</span>\n</div>") .data("<div id=\"feed\">\n<span>1</span>\n</div>")
.build(); .build();
@ -111,13 +109,11 @@ This event is used to remove fragments from the DOM.
##### Options ##### 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. - `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`. - `useViewTransition` Whether to use view transitions, if not provided the Datastar client side **_will_** default to `false`.
```java ```java
RemoveFragments event = RemoveFragments.builder() RemoveFragments event = RemoveFragments.builder()
.selector("#feed") .selector("#feed")
.settleDuration(500)
.useViewTransition(true) .useViewTransition(true)
.build(); .build();
``` ```

View File

@ -9,9 +9,6 @@ public final class Consts {
public static final String DATASTAR_KEY = "datastar"; public static final String DATASTAR_KEY = "datastar";
public static final String VERSION = "1.0.0-beta.9"; 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. // 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; public static final int DEFAULT_SSE_RETRY_DURATION = 1000;
@ -33,7 +30,6 @@ public final class Consts {
// Dataline literals. // Dataline literals.
public static final String SELECTOR_DATALINE_LITERAL = "selector "; public static final String SELECTOR_DATALINE_LITERAL = "selector ";
public static final String MERGE_MODE_DATALINE_LITERAL = "mergeMode "; 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 FRAGMENTS_DATALINE_LITERAL = "fragments ";
public static final String USE_VIEW_TRANSITION_DATALINE_LITERAL = "useViewTransition "; public static final String USE_VIEW_TRANSITION_DATALINE_LITERAL = "useViewTransition ";
public static final String SIGNALS_DATALINE_LITERAL = "signals "; 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> { public static final class Builder extends AbstractBuilder<MergeFragments> {
private String selector; private String selector;
private FragmentMergeMode mergeMode = DEFAULT_FRAGMENT_MERGE_MODE; // Default 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 boolean useViewTransition = DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; // Default
private String rawData; private String rawData;
@ -45,11 +44,6 @@ public final class MergeFragments extends AbstractDatastarEvent {
return this; return this;
} }
public Builder settleDuration(int settleDuration) {
this.settleDuration = settleDuration;
return this;
}
public Builder useViewTransition(boolean useViewTransition) { public Builder useViewTransition(boolean useViewTransition) {
this.useViewTransition = useViewTransition; this.useViewTransition = useViewTransition;
return this; return this;
@ -78,11 +72,6 @@ public final class MergeFragments extends AbstractDatastarEvent {
dataLines.add(MERGE_MODE_DATALINE_LITERAL + mergeMode); 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 // Add useViewTransition if true
if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) { if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
dataLines.add(USE_VIEW_TRANSITION_DATALINE_LITERAL + useViewTransition); 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> { public static final class Builder extends AbstractBuilder<RemoveFragments> {
private String selector; private String selector;
private int settleDuration = DEFAULT_FRAGMENTS_SETTLE_DURATION; // Default
private boolean useViewTransition = DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; // Default private boolean useViewTransition = DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; // Default
private Builder() { private Builder() {
} }
@ -34,11 +33,6 @@ public final class RemoveFragments extends AbstractDatastarEvent {
return this; return this;
} }
public Builder settleDuration(int settleDuration) {
this.settleDuration = settleDuration;
return this;
}
public Builder useViewTransition(boolean useViewTransition) { public Builder useViewTransition(boolean useViewTransition) {
this.useViewTransition = useViewTransition; this.useViewTransition = useViewTransition;
return this; return this;
@ -55,11 +49,6 @@ public final class RemoveFragments extends AbstractDatastarEvent {
// Add selector // Add selector
dataLines.add(SELECTOR_DATALINE_LITERAL + selector.trim()); 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 // Add useViewTransition if true
if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) { if (useViewTransition != DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
dataLines.add(USE_VIEW_TRANSITION_DATALINE_LITERAL + useViewTransition); dataLines.add(USE_VIEW_TRANSITION_DATALINE_LITERAL + useViewTransition);

View File

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

View File

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

View File

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

View File

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

View File

@ -12,9 +12,6 @@ class Consts
public const DATASTAR_KEY = 'datastar'; public const DATASTAR_KEY = 'datastar';
public const VERSION = '1.0.0-beta.9'; 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. // 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; public const DEFAULT_SSE_RETRY_DURATION = 1000;
@ -36,7 +33,6 @@ class Consts
// Dataline literals. // Dataline literals.
public const SELECTOR_DATALINE_LITERAL = 'selector '; public const SELECTOR_DATALINE_LITERAL = 'selector ';
public const MERGE_MODE_DATALINE_LITERAL = 'mergeMode '; public const MERGE_MODE_DATALINE_LITERAL = 'mergeMode ';
public const SETTLE_DURATION_DATALINE_LITERAL = 'settleDuration ';
public const FRAGMENTS_DATALINE_LITERAL = 'fragments '; public const FRAGMENTS_DATALINE_LITERAL = 'fragments ';
public const USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition '; public const USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition ';
public const SIGNALS_DATALINE_LITERAL = 'signals '; public const SIGNALS_DATALINE_LITERAL = 'signals ';

View File

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

View File

@ -17,7 +17,6 @@ class MergeFragments implements EventInterface
public string $fragments; public string $fragments;
public string $selector = ''; public string $selector = '';
public FragmentMergeMode $mergeMode = Consts::DEFAULT_FRAGMENT_MERGE_MODE; 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 bool $useViewTransition = Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS;
public function __construct(string $fragments, array $options = []) 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); $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) { if ($this->useViewTransition !== Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
$dataLines[] = $this->getDataLine(Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL, $this->getBooleanAsString($this->useViewTransition)); $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; use EventTrait;
public string $selector; public string $selector;
public int $settleDuration = Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION;
public bool $useViewTransition = Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS; public bool $useViewTransition = Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS;
public function __construct(string $selector, array $options = []) public function __construct(string $selector, array $options = [])
@ -42,10 +41,6 @@ class RemoveFragments implements EventInterface
$this->getDataLine(Consts::SELECTOR_DATALINE_LITERAL, $this->selector), $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) { if ($this->useViewTransition !== Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS) {
$dataLines[] = $this->getDataLine(Consts::USE_VIEW_TRANSITION_DATALINE_LITERAL, $this->getBooleanAsString($this->useViewTransition)); $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, [ $event = new MergeFragments($content, [
'selector' => 'selector', 'selector' => 'selector',
'mergeMode' => FragmentMergeMode::Append, 'mergeMode' => FragmentMergeMode::Append,
'settleDuration' => 1000,
'useViewTransition' => true, 'useViewTransition' => true,
]); ]);
expect($event->getDataLines()) expect($event->getDataLines())
->toBe([ ->toBe([
'data: selector selector', 'data: selector selector',
'data: mergeMode append', 'data: mergeMode append',
'data: settleDuration 1000',
'data: useViewTransition true', 'data: useViewTransition true',
'data: fragments ' . $content, 'data: fragments ' . $content,
]); ]);
@ -42,7 +40,6 @@ test('Default options are not output', function() {
$event = new MergeFragments($content, [ $event = new MergeFragments($content, [
'selector' => '', 'selector' => '',
'mergeMode' => FragmentMergeMode::Morph, 'mergeMode' => FragmentMergeMode::Morph,
'settleDuration' => Consts::DEFAULT_FRAGMENTS_SETTLE_DURATION,
'useViewTransition' => false, 'useViewTransition' => false,
]); ]);
expect($event->getDataLines()) expect($event->getDataLines())

View File

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

View File

@ -55,8 +55,6 @@ VERSION = "1.0.0-beta.9"
#region Default durations #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. # The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
DefaultSseRetryDuration = 1000 DefaultSseRetryDuration = 1000
@ -72,7 +70,6 @@ DefaultExecuteScriptAttributes = "type module"
#region Dataline literals #region Dataline literals
SelectorDatalineLiteral = "selector" SelectorDatalineLiteral = "selector"
MergeModeDatalineLiteral = "mergeMode" MergeModeDatalineLiteral = "mergeMode"
SettleDurationDatalineLiteral = "settleDuration"
FragmentsDatalineLiteral = "fragments" FragmentsDatalineLiteral = "fragments"
UseViewTransitionDatalineLiteral = "useViewTransition" UseViewTransitionDatalineLiteral = "useViewTransition"
SignalsDatalineLiteral = "signals" SignalsDatalineLiteral = "signals"

View File

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

View File

@ -6,9 +6,6 @@ module Datastar
DATASTAR_KEY = 'datastar' DATASTAR_KEY = 'datastar'
VERSION = '1.0.0-beta.9' 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. # The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
DEFAULT_SSE_RETRY_DURATION = 1000 DEFAULT_SSE_RETRY_DURATION = 1000
@ -57,7 +54,6 @@ module Datastar
# Dataline literals. # Dataline literals.
SELECTOR_DATALINE_LITERAL = 'selector' SELECTOR_DATALINE_LITERAL = 'selector'
MERGE_MODE_DATALINE_LITERAL = 'mergeMode' MERGE_MODE_DATALINE_LITERAL = 'mergeMode'
SETTLE_DURATION_DATALINE_LITERAL = 'settleDuration'
FRAGMENTS_DATALINE_LITERAL = 'fragments' FRAGMENTS_DATALINE_LITERAL = 'fragments'
USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition' USE_VIEW_TRANSITION_DATALINE_LITERAL = 'useViewTransition'
SIGNALS_DATALINE_LITERAL = 'signals' SIGNALS_DATALINE_LITERAL = 'signals'

View File

@ -17,7 +17,6 @@ module Datastar
'retry' => Consts::DEFAULT_SSE_RETRY_DURATION, 'retry' => Consts::DEFAULT_SSE_RETRY_DURATION,
Consts::AUTO_REMOVE_DATALINE_LITERAL => Consts::DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE, Consts::AUTO_REMOVE_DATALINE_LITERAL => Consts::DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE,
Consts::MERGE_MODE_DATALINE_LITERAL => Consts::DEFAULT_FRAGMENT_MERGE_MODE, 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::USE_VIEW_TRANSITION_DATALINE_LITERAL => Consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
Consts::ONLY_IF_MISSING_DATALINE_LITERAL => Consts::DEFAULT_MERGE_SIGNALS_ONLY_IF_MISSING, Consts::ONLY_IF_MISSING_DATALINE_LITERAL => Consts::DEFAULT_MERGE_SIGNALS_ONLY_IF_MISSING,
}.freeze }.freeze

View File

@ -75,26 +75,24 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments( dispatcher.merge_fragments(
%(<div id="foo">\n<span>hello</span>\n</div>\n), %(<div id="foo">\n<span>hello</span>\n</div>\n),
id: 72, id: 72,
retry_duration: 2000, retry_duration: 2000
settle_duration: 1000
) )
socket = TestSocket.new socket = TestSocket.new
dispatcher.response.body.call(socket) dispatcher.response.body.call(socket)
expect(socket.open).to be(false) 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 end
it 'omits retry if using default value' do it 'omits retry if using default value' do
dispatcher.merge_fragments( dispatcher.merge_fragments(
%(<div id="foo">\n<span>hello</span>\n</div>\n), %(<div id="foo">\n<span>hello</span>\n</div>\n),
id: 72, id: 72,
retry_duration: 1000, retry_duration: 1000
settle_duration: 1000
) )
socket = TestSocket.new socket = TestSocket.new
dispatcher.response.body.call(socket) dispatcher.response.body.call(socket)
expect(socket.open).to be(false) 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 end
it 'works with #call(view_context:) interfaces' do it 'works with #call(view_context:) interfaces' do
@ -105,12 +103,11 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments( dispatcher.merge_fragments(
template_class, template_class,
id: 72, id: 72,
retry_duration: 2000, retry_duration: 2000
settle_duration: 1000
) )
socket = TestSocket.new socket = TestSocket.new
dispatcher.response.body.call(socket) 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
it 'works with #render_in(view_context, &) interfaces' do it 'works with #render_in(view_context, &) interfaces' do
@ -121,12 +118,11 @@ RSpec.describe Datastar::Dispatcher do
dispatcher.merge_fragments( dispatcher.merge_fragments(
template_class, template_class,
id: 72, id: 72,
retry_duration: 2000, retry_duration: 2000
settle_duration: 1000
) )
socket = TestSocket.new socket = TestSocket.new
dispatcher.response.body.call(socket) 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
end end
@ -140,11 +136,11 @@ RSpec.describe Datastar::Dispatcher do
end end
it 'takes D* options' do 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 socket = TestSocket.new
dispatcher.response.body.call(socket) dispatcher.response.body.call(socket)
expect(socket.open).to be(false) 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
end end

View File

@ -7,8 +7,6 @@ pub const _VERSION: &str = "1.0.0-beta.9";
// #region Default durations // #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. /// 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; 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 SELECTOR_DATALINE_LITERAL: &str = "selector";
pub const MERGE_MODE_DATALINE_LITERAL: &str = "mergeMode"; 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 FRAGMENTS_DATALINE_LITERAL: &str = "fragments";
pub const USE_VIEW_TRANSITION_DATALINE_LITERAL: &str = "useViewTransition"; pub const USE_VIEW_TRANSITION_DATALINE_LITERAL: &str = "useViewTransition";
pub const SIGNALS_DATALINE_LITERAL: &str = "signals"; pub const SIGNALS_DATALINE_LITERAL: &str = "signals";

View File

@ -25,7 +25,6 @@ use {
/// yield MergeFragments::new("<h1>Hello, world!</h1>") /// yield MergeFragments::new("<h1>Hello, world!</h1>")
/// .selector("body") /// .selector("body")
/// .merge_mode(FragmentMergeMode::Append) /// .merge_mode(FragmentMergeMode::Append)
/// .settle_duration(Duration::from_millis(1000))
/// .use_view_transition(true) /// .use_view_transition(true)
/// .into(); /// .into();
/// }); /// });
@ -47,9 +46,6 @@ pub struct MergeFragments {
/// The mode to use when merging the fragment into the DOM. /// The mode to use when merging the fragment into the DOM.
/// If not provided the Datastar client side will default to [`FragmentMergeMode::Morph`]. /// If not provided the Datastar client side will default to [`FragmentMergeMode::Morph`].
pub merge_mode: FragmentMergeMode, 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`. /// Whether to use view transitions, if not provided the Datastar client side will default to `false`.
pub use_view_transition: bool, pub use_view_transition: bool,
} }
@ -63,7 +59,6 @@ impl MergeFragments {
fragments: fragments.into(), fragments: fragments.into(),
selector: None, selector: None,
merge_mode: FragmentMergeMode::default(), merge_mode: FragmentMergeMode::default(),
settle_duration: Duration::from_millis(consts::DEFAULT_FRAGMENTS_SETTLE_DURATION),
use_view_transition: consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS, use_view_transition: consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS,
} }
} }
@ -92,12 +87,6 @@ impl MergeFragments {
self 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. /// Sets the `use_view_transition` of the [`MergeFragments`] event.
pub fn use_view_transition(mut self, use_view_transition: bool) -> Self { pub fn use_view_transition(mut self, use_view_transition: bool) -> Self {
self.use_view_transition = use_view_transition; 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 { if val.use_view_transition != consts::DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS {
data.push(format!( data.push(format!(
"{} {}", "{} {}",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,8 +8,6 @@ export const VERSION = "1.0.0-beta.9";
// #region Default durations // #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. // The default duration for retrying SSE on connection reset. This is part of the underlying retry mechanism of SSE.
export const DefaultSseRetryDurationMs = 1000; export const DefaultSseRetryDurationMs = 1000;
@ -41,7 +39,6 @@ export const DefaultExecuteScriptAutoRemove = true;
export const DatastarDatalineSelector = "selector" export const DatastarDatalineSelector = "selector"
export const DatastarDatalineMergeMode = "mergeMode" export const DatastarDatalineMergeMode = "mergeMode"
export const DatastarDatalineSettleDuration = "settleDuration"
export const DatastarDatalineFragments = "fragments" export const DatastarDatalineFragments = "fragments"
export const DatastarDatalineUseViewTransition = "useViewTransition" export const DatastarDatalineUseViewTransition = "useViewTransition"
export const DatastarDatalineSignals = "signals" export const DatastarDatalineSignals = "signals"

View File

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

View File

@ -34,9 +34,6 @@ pub const MergeFragmentsOptions = struct {
selector: ?[]const u8 = null, selector: ?[]const u8 = null,
/// The mode to use when merging the fragment into the DOM. /// The mode to use when merging the fragment into the DOM.
merge_mode: consts.FragmentMergeMode = consts.default_fragment_merge_mode, 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. /// Whether to use view transitions.
use_view_transition: bool = consts.default_fragments_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. /// `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 /// 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, 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. /// Whether to use view transitions.
use_view_transition: bool = consts.default_fragments_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) { if (options.use_view_transition != consts.default_fragments_use_view_transitions) {
try writer.print( try writer.print(
consts.use_view_transition_dataline_literal ++ " {}\n", consts.use_view_transition_dataline_literal ++ " {}\n",
@ -281,15 +266,6 @@ pub fn removeFragments(
errdefer data.deinit(self.allocator); errdefer data.deinit(self.allocator);
const writer = data.writer(); 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) { if (options.use_view_transition != consts.default_fragments_use_view_transitions) {
try writer.print( try writer.print(
consts.use_view_transition_dataline_literal ++ " {}\n", consts.use_view_transition_dataline_literal ++ " {}\n",

View File

@ -9,8 +9,6 @@ pub const version = "1.0.0-beta.9";
// #region Default durations // #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. /// 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; 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 selector_dataline_literal = "selector";
pub const merge_mode_dataline_literal = "mergeMode"; pub const merge_mode_dataline_literal = "mergeMode";
pub const settle_duration_dataline_literal = "settleDuration";
pub const fragments_dataline_literal = "fragments"; pub const fragments_dataline_literal = "fragments";
pub const use_view_transition_dataline_literal = "useViewTransition"; pub const use_view_transition_dataline_literal = "useViewTransition";
pub const signals_dataline_literal = "signals"; pub const signals_dataline_literal = "signals";

View File

@ -20,7 +20,6 @@ const MergeFragments = struct {
retryDuration: ?u32 = null, retryDuration: ?u32 = null,
selector: ?[]const u8 = null, selector: ?[]const u8 = null,
mergeMode: ?consts.FragmentMergeMode = null, mergeMode: ?consts.FragmentMergeMode = null,
settleDuration: ?u32 = null,
useViewTransition: ?bool = null, useViewTransition: ?bool = null,
}; };
@ -35,7 +34,6 @@ const RemoveFragments = struct {
selector: []const u8, selector: []const u8,
eventId: ?[]const u8 = null, eventId: ?[]const u8 = null,
retryDuration: ?u32 = null, retryDuration: ?u32 = null,
settleDuration: ?u32 = null,
useViewTransition: ?bool = 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, .retry_duration = ev.retryDuration orelse consts.default_sse_retry_duration,
.selector = ev.selector, .selector = ev.selector,
.merge_mode = ev.mergeMode orelse consts.default_fragment_merge_mode, .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, .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, .event_id = ev.eventId,
.retry_duration = ev.retryDuration orelse consts.default_sse_retry_duration, .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, .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) time.Sleep(2 * time.Second)
datastar.NewSSE(w, r).MergeFragmentTempl( datastar.NewSSE(w, r).MergeFragmentTempl(
lazyLoadGraph(), lazyLoadGraph(),
datastar.WithSettleDuration(1*time.Second),
) )
}) })

View File

@ -33,8 +33,7 @@ func setupHowTosLoadMore(howTosRedirect chi.Router) error {
if newOffset < max { if newOffset < max {
sse.MergeSignals([]byte(fmt.Sprintf(`{offset: %d}`, newOffset))) sse.MergeSignals([]byte(fmt.Sprintf(`{offset: %d}`, newOffset)))
} else { } else {
// TODO: set settle duration back to `0` or remove entirely sse.RemoveFragments(`#load-more`)
sse.RemoveFragments(`#load-more`, datastar.WithRemoveSettleDuration(1))
} }
sse.MergeFragments(fmt.Sprintf(`<div class="text-primary font-bold">Item %d</div>`, newOffset), 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 event: datastar-merge-fragments
id: 92680296792588350 id: 92680296792588350
data: mergeMode morph data: mergeMode morph
data: settleDuration 0
data: fragment data: fragment
<div id="lazy_tabs"> <div id="lazy_tabs">
<div class="tabs tabs-bordered"> <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. 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 ### 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: 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 ```html
<div data-show="$fetching">Spinner</div>
<button <button
id="submit_request_in_flight" id="submit_request_in_flight"
data-on-click="@post('/examples/animations/data/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 Submit
</button> </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. 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 ## Demo
<style>
tr.deactivate.datastar-settling td {
background: lightcoral;
}
tr.activate.datastar-settling td {
background: darkseagreen;
}
tr td {
transition: all 1.2s;
}
</style>
<div <div
id="bulk_update" id="bulk_update"
data-on-load="@get('/examples/bulk_update/data')" 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`. 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: The server will either activate or deactivate the checked users and then rerender the tbody tag with updated rows.
```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.

View File

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

View File

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

View File

@ -23,13 +23,11 @@ This last element contains a listener which, when scrolled into view, will trigg
event: datastar-merge-fragments event: datastar-merge-fragments
data: selector #more_btn data: selector #more_btn
data: mergeMode morph 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> 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 event: datastar-merge-fragments
data: selector #click_to_load_rows data: selector #click_to_load_rows
data: mergeMode append 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>" 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 ....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 ## Demo
Don't scroll too far, there are consequences Don't scroll too far, there are consequences.
<div> <div>
<div <div

View File

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

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 before` | Inserts the fragment before the target as a sibling. |
| `data: mergeMode after` | Inserts the fragment after 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: 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: 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. | | `data: fragments` | The HTML fragments to merge into the DOM. |
@ -43,7 +42,6 @@ Sample output showing all options:
event: datastar-merge-fragments event: datastar-merge-fragments
data: selector #foo data: selector #foo
data: mergeMode append data: mergeMode append
data: settleDuration 500
data: useViewTransition true data: useViewTransition true
data: fragments <div> data: fragments <div>
data: fragments Hello, world! data: fragments Hello, world!