Fix remove fragment (#665)
* Replace delay function call * Add test * Improve tests * Add release note
This commit is contained in:
parent
2a16577829
commit
1e9c7a820b
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -4,15 +4,8 @@ Each tagged version of Datastar is accompanied by a release note. Read the [rele
|
||||||
|
|
||||||
# WIP Release Notes
|
# WIP Release Notes
|
||||||
|
|
||||||
## v1.0.0-beta.6
|
## v1.0.0-beta.7
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- The `data-on-load` callback is now delayed to the next microtask, making it possible to place the `data-indicator` attribute later on the same element.
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed a bug in which the `data-on-signals-change` attribute expression was not being executed when signal values changed ([#641](https://github.com/starfederation/datastar/issues/641)).
|
- Fixed a bug in which `datastar-remove-fragments` events were not having any effect ([#664](https://github.com/starfederation/datastar/issues/664)).
|
||||||
- Fixed a bug in which the signal created by `data-ref` was being removed during the cleanup process ([#642](https://github.com/starfederation/datastar/issues/642)).
|
|
||||||
- Fixed a bug in which errors were being caught in preact core, which was obfuscating the original error ([#643](https://github.com/starfederation/datastar/issues/643)).
|
|
||||||
- Fixed a bug in which morphed DOM elements could lose their focus, due to a change of behavior in Idiomorph ([#645](https://github.com/starfederation/datastar/issues/645)).
|
|
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
|
@ -18,7 +18,6 @@ import {
|
||||||
} from '../../../../engine/types'
|
} from '../../../../engine/types'
|
||||||
import { elUniqId, walkDOM } from '../../../../utils/dom'
|
import { elUniqId, walkDOM } from '../../../../utils/dom'
|
||||||
import { camel, isBoolString } from '../../../../utils/text'
|
import { camel, isBoolString } from '../../../../utils/text'
|
||||||
import { delay } from '../../../../utils/timing'
|
|
||||||
import {
|
import {
|
||||||
docWithViewTransitionAPI,
|
docWithViewTransitionAPI,
|
||||||
supportsViewTransitions,
|
supportsViewTransitions,
|
||||||
|
@ -94,7 +93,6 @@ function applyToTargets(
|
||||||
walkDOM(fragmentWithIDs, (el) => {
|
walkDOM(fragmentWithIDs, (el) => {
|
||||||
if (!el.id?.length && Object.keys(el.dataset).length) {
|
if (!el.id?.length && Object.keys(el.dataset).length) {
|
||||||
el.id = elUniqId(el)
|
el.id = elUniqId(el)
|
||||||
console.log(el.id)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -168,7 +166,7 @@ function applyToTargets(
|
||||||
const cl = modifiedTarget.classList
|
const cl = modifiedTarget.classList
|
||||||
cl?.add(SWAPPING_CLASS)
|
cl?.add(SWAPPING_CLASS)
|
||||||
|
|
||||||
delay(() => {
|
setTimeout(() => {
|
||||||
initialTarget.classList.remove(SWAPPING_CLASS)
|
initialTarget.classList.remove(SWAPPING_CLASS)
|
||||||
cl?.remove(SWAPPING_CLASS)
|
cl?.remove(SWAPPING_CLASS)
|
||||||
}, settleDuration)
|
}, settleDuration)
|
||||||
|
@ -177,7 +175,7 @@ function applyToTargets(
|
||||||
|
|
||||||
if (cl && originalHTML !== revisedHTML) {
|
if (cl && originalHTML !== revisedHTML) {
|
||||||
cl.add(SETTLING_CLASS)
|
cl.add(SETTLING_CLASS)
|
||||||
delay(() => {
|
setTimeout(() => {
|
||||||
cl.remove(SETTLING_CLASS)
|
cl.remove(SETTLING_CLASS)
|
||||||
}, settleDuration)
|
}, settleDuration)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import {
|
||||||
import { initErr } from '../../../../engine/errors'
|
import { initErr } from '../../../../engine/errors'
|
||||||
import { PluginType, type WatcherPlugin } from '../../../../engine/types'
|
import { PluginType, type WatcherPlugin } from '../../../../engine/types'
|
||||||
import { isBoolString } from '../../../../utils/text'
|
import { isBoolString } from '../../../../utils/text'
|
||||||
import { delay } from '../../../../utils/timing'
|
|
||||||
import {
|
import {
|
||||||
docWithViewTransitionAPI,
|
docWithViewTransitionAPI,
|
||||||
supportsViewTransitions,
|
supportsViewTransitions,
|
||||||
|
@ -43,7 +42,7 @@ export const RemoveFragments: WatcherPlugin = {
|
||||||
target.classList.add(SWAPPING_CLASS)
|
target.classList.add(SWAPPING_CLASS)
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(() => {
|
setTimeout(() => {
|
||||||
for (const target of removeTargets) {
|
for (const target of removeTargets) {
|
||||||
target.remove()
|
target.remove()
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ export const On: AttributePlugin = {
|
||||||
|
|
||||||
if (key === 'load') {
|
if (key === 'load') {
|
||||||
// Delay the callback to the next microtask so that indicators can be set
|
// Delay the callback to the next microtask so that indicators can be set
|
||||||
delay(() => callback(), 0)()
|
setTimeout(() => callback(), 0)
|
||||||
return () => {}
|
return () => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import "time"
|
||||||
const (
|
const (
|
||||||
DatastarKey = "datastar"
|
DatastarKey = "datastar"
|
||||||
Version = "1.0.0-beta.6"
|
Version = "1.0.0-beta.6"
|
||||||
VersionClientByteSize = 39873
|
VersionClientByteSize = 39885
|
||||||
VersionClientByteSizeGzip = 14814
|
VersionClientByteSizeGzip = 14805
|
||||||
|
|
||||||
//region Default durations
|
//region Default durations
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,11 @@ func setupTests(ctx context.Context, router chi.Router, signals sessions.Store)
|
||||||
Label: "tests",
|
Label: "tests",
|
||||||
Links: []*SidebarLink{
|
Links: []*SidebarLink{
|
||||||
{ID: "key_casing"},
|
{ID: "key_casing"},
|
||||||
|
{ID: "merge_fragment"},
|
||||||
{ID: "merge_fragment_signal"},
|
{ID: "merge_fragment_signal"},
|
||||||
{ID: "on_load"},
|
{ID: "on_load"},
|
||||||
{ID: "ref"},
|
{ID: "ref"},
|
||||||
|
{ID: "remove_fragment"},
|
||||||
{ID: "signals_change"},
|
{ID: "signals_change"},
|
||||||
{ID: "signals_change_path"},
|
{ID: "signals_change_path"},
|
||||||
},
|
},
|
||||||
|
@ -87,8 +89,10 @@ func setupTests(ctx context.Context, router chi.Router, signals sessions.Store)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := errors.Join(
|
if err := errors.Join(
|
||||||
|
setupTestsMergeFragment(testsRouter),
|
||||||
setupTestsMergeFragmentSignal(testsRouter),
|
setupTestsMergeFragmentSignal(testsRouter),
|
||||||
setupTestsOnLoad(testsRouter),
|
setupTestsOnLoad(testsRouter),
|
||||||
|
setupTestsRemoveFragment(testsRouter),
|
||||||
); err != nil {
|
); err != nil {
|
||||||
panic(fmt.Sprintf("error setting up tests routes: %s", err))
|
panic(fmt.Sprintf("error setting up tests routes: %s", err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
datastar "github.com/starfederation/datastar/sdk/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setupTestsMergeFragment(testsRouter chi.Router) error {
|
||||||
|
|
||||||
|
testsRouter.Get("/merge_fragment/data", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
sse := datastar.NewSSE(w, r)
|
||||||
|
c := mergeFragmentTest()
|
||||||
|
sse.MergeFragmentTempl(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package site
|
||||||
|
|
||||||
|
templ mergeFragmentTest() {
|
||||||
|
<code id="result">1</code>
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package site
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
datastar "github.com/starfederation/datastar/sdk/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setupTestsRemoveFragment(testsRouter chi.Router) error {
|
||||||
|
|
||||||
|
testsRouter.Delete("/remove_fragment/data", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
sse := datastar.NewSSE(w, r)
|
||||||
|
sse.RemoveFragments("#remove")
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestKeyCasing(t *testing.T) {
|
func TestKeyCasing(t *testing.T) {
|
||||||
setupLoadPageTest(t, "tests/key_casing")
|
setupPageTestOnLoad(t, "tests/key_casing")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package smoketests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMergeFragment(t *testing.T) {
|
||||||
|
setupPageTestOnClick(t, "tests/merge_fragment")
|
||||||
|
}
|
|
@ -4,6 +4,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeFragment(t *testing.T) {
|
func TestMergeFragmentSignal(t *testing.T) {
|
||||||
setupButtonPageTest(t, "tests/merge_fragment_signal")
|
setupPageTestOnClick(t, "tests/merge_fragment_signal")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExampleOnLoad(t *testing.T) {
|
func TestExampleOnLoad(t *testing.T) {
|
||||||
setupLoadPageTest(t, "tests/on_load")
|
setupPageTestOnLoad(t, "tests/on_load")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRef(t *testing.T) {
|
func TestRef(t *testing.T) {
|
||||||
setupLoadPageTest(t, "tests/ref")
|
setupPageTestOnLoad(t, "tests/ref")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package smoketests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRemoveFragment(t *testing.T) {
|
||||||
|
setupPageTestOnClick(t, "tests/remove_fragment")
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ func setupPageTest(t *testing.T, subURL string, gen func(runner runnerFn)) {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupButtonPageTest(t *testing.T, subURL string) {
|
func setupPageTestOnClick(t *testing.T, subURL string) {
|
||||||
setupPageTest(t, subURL, func(runner runnerFn) {
|
setupPageTest(t, subURL, func(runner runnerFn) {
|
||||||
runner(subURL, func(t *testing.T, page *rod.Page) {
|
runner(subURL, func(t *testing.T, page *rod.Page) {
|
||||||
result := page.MustElement("#result")
|
result := page.MustElement("#result")
|
||||||
|
@ -83,7 +83,7 @@ func setupButtonPageTest(t *testing.T, subURL string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLoadPageTest(t *testing.T, subURL string) {
|
func setupPageTestOnLoad(t *testing.T, subURL string) {
|
||||||
setupPageTest(t, subURL, func(runner runnerFn) {
|
setupPageTest(t, subURL, func(runner runnerFn) {
|
||||||
runner(subURL, func(t *testing.T, page *rod.Page) {
|
runner(subURL, func(t *testing.T, page *rod.Page) {
|
||||||
result := page.MustElement("#result")
|
result := page.MustElement("#result")
|
||||||
|
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExampleSignalsChangePath(t *testing.T) {
|
func TestExampleSignalsChangePath(t *testing.T) {
|
||||||
setupButtonPageTest(t, "tests/signals_change_path")
|
setupPageTestOnClick(t, "tests/signals_change_path")
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExampleSignalsChange(t *testing.T) {
|
func TestExampleSignalsChange(t *testing.T) {
|
||||||
setupButtonPageTest(t, "tests/signals_change")
|
setupPageTestOnClick(t, "tests/signals_change")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Merge Fregment
|
||||||
|
|
||||||
|
Tests that merging a fragment works.
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button data-on-click="@get('/tests/merge_fragment/data')" class="btn">Merge</button>
|
||||||
|
<hr />
|
||||||
|
Result:
|
||||||
|
<code id="result">0</code>
|
||||||
|
<hr />
|
||||||
|
Expected result on click: <code>1</code>
|
||||||
|
</div>
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Remove Fregment
|
||||||
|
|
||||||
|
Tests that removing a fragment works.
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button data-on-click="@delete('/tests/remove_fragment/data')" class="btn">Remove</button>
|
||||||
|
<hr />
|
||||||
|
Result:
|
||||||
|
<code id="result"><span id="remove">0</span>1</code>
|
||||||
|
<hr />
|
||||||
|
Expected result on click: <code>1</code>
|
||||||
|
</div>
|
Loading…
Reference in New Issue