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:
parent
39cb56db3e
commit
c35b85ce4e
|
@ -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)).
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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]])))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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 ")
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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])))))
|
||||||
|
|
||||||
;; -----------------------------------------------------------------------------
|
;; -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,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 "
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
-}
|
-}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
```
|
```
|
||||||
|
|
|
@ -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 ";
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>",
|
||||||
|
|
|
@ -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"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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 ';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
|
|
|
@ -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!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
"retryDuration": 2000,
|
"retryDuration": 2000,
|
||||||
"selector": "div",
|
"selector": "div",
|
||||||
"mergeMode": "append",
|
"mergeMode": "append",
|
||||||
"settleDuration": 1000,
|
|
||||||
"useViewTransition": true
|
"useViewTransition": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
"selector": "#target",
|
"selector": "#target",
|
||||||
"eventId": "event1",
|
"eventId": "event1",
|
||||||
"retryDuration": 2000,
|
"retryDuration": 2000,
|
||||||
"settleDuration": 1000,
|
|
||||||
"useViewTransition": true
|
"useViewTransition": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
{
|
{
|
||||||
"type": "removeFragments",
|
"type": "removeFragments",
|
||||||
"selector": "#target",
|
"selector": "#target",
|
||||||
"settleDuration": 300,
|
|
||||||
"useViewTransition": false
|
"useViewTransition": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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]: {
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -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),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 PUT’s 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 PUT’s 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.
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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.
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -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!
|
||||||
|
|
Loading…
Reference in New Issue