0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

Fix Svelte view transition state persistence (#12006)

Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com>
This commit is contained in:
Johannes Spohr 2024-09-17 16:11:32 +02:00 committed by GitHub
parent daca9951f4
commit a582cb6124
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 85 additions and 22 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/svelte': patch
---
Fix Svelte component view transition state persistence

View file

@ -1,5 +1,6 @@
<script lang="ts">
let count = 0;
export let prefix = "";
function add() {
count += 1;
@ -11,9 +12,9 @@
</script>
<div class="counter">
<button on:click={subtract}>-</button>
<pre>{count}</pre>
<button on:click={add}>+</button>
<button on:click={subtract} class="decrement">-</button>
<pre>{prefix}{count}</pre>
<button on:click={add} class="increment">+</button>
</div>
<div class="message">
<slot />

View file

@ -0,0 +1,11 @@
---
import Counter from '../components/SvelteCounter.svelte';
import Layout from '../components/Layout.astro';
export const prerender = false;
---
<Layout>
<p id="island-one">Page 1</p>
<a id="click-two" href="/island-svelte-two">go to 2</a>
<Counter prefix="A" client:load transition:persist transition:name="counter"/>
</Layout>

View file

@ -0,0 +1,11 @@
---
import Counter from '../components/SvelteCounter.svelte';
import Layout from '../components/Layout.astro';
export const prerender = false;
---
<Layout>
<p id="island-two">Page 2</p>
<a id="click-one" href="/island-svelte-one">go to 1</a>
<Counter prefix="B" client:load transition:persist transition:name="counter"/>
</Layout>

View file

@ -543,8 +543,8 @@ test.describe('View Transitions', () => {
const pageTitle = page.locator('.page');
await expect(pageTitle).toHaveText('Island 2');
});
test('Solid Islands can persist using transition:persist', async ({ page, astro }) => {
test('Solid Islands can persist using transition:persist', async ({ page, astro }) => {
// Go to page 1
await page.goto(astro.resolveUrl('/island-solid-one'));
let cnt = page.locator('.counter pre');
@ -569,6 +569,24 @@ test.describe('View Transitions', () => {
await expect(cnt).toHaveText('A1');
});
test('Svelte Islands can persist using transition:persist', async ({ page, astro }) => {
// Go to page 1
await page.goto(astro.resolveUrl('/island-svelte-one'));
let cnt = page.locator('.counter pre');
await expect(cnt).toHaveText('A0');
await page.click('.increment');
await expect(cnt).toHaveText('A1');
// Navigate to page 2
await page.click('#click-two');
let p = page.locator('#island-two');
await expect(p).toBeVisible();
cnt = page.locator('.counter pre');
// Count should remain, but the prefix should be updated
await expect(cnt).toHaveText('B1');
});
test('Vue Islands can persist using transition:persist', async ({ page, astro }) => {
// Go to page 1
await page.goto(astro.resolveUrl('/island-vue-one'));

View file

@ -1,5 +1,7 @@
import { createRawSnippet, hydrate, mount, unmount } from 'svelte';
const existingApplications = new WeakMap();
export default (element) => {
return async (Component, props, slotted, { client }) => {
if (!element.hasAttribute('ssr')) return;
@ -21,15 +23,23 @@ export default (element) => {
}
const bootstrap = client !== 'only' ? hydrate : mount;
const component = bootstrap(Component, {
target: element,
props: {
if (existingApplications.has(element)) {
existingApplications.get(element).$set({
...props,
children,
$$slots,
},
});
});
} else {
const component = bootstrap(Component, {
target: element,
props: {
...props,
children,
$$slots,
},
});
existingApplications.set(element, component);
}
element.addEventListener('astro:unmount', () => unmount(component), { once: true });
};

View file

@ -3,6 +3,8 @@ const noop = () => {};
let originalConsoleWarning;
let consoleFilterRefs = 0;
const existingApplications = new WeakMap();
export default (element) => {
return (Component, props, slotted, { client }) => {
if (!element.hasAttribute('ssr')) return;
@ -14,18 +16,23 @@ export default (element) => {
try {
if (import.meta.env.DEV) useConsoleFilter();
const component = new Component({
target: element,
props: {
...props,
$$slots: slots,
$$scope: { ctx: [] },
},
hydrate: client !== 'only',
$$inline: true,
});
if (existingApplications.has(element)) {
existingApplications.get(element).$set({ ...props, $$slots: slots, $$scope: { ctx: [] } });
} else {
const component = new Component({
target: element,
props: {
...props,
$$slots: slots,
$$scope: { ctx: [] },
},
hydrate: client !== 'only',
$$inline: true,
});
existingApplications.set(element, component);
element.addEventListener('astro:unmount', () => component.$destroy(), { once: true });
element.addEventListener('astro:unmount', () => component.$destroy(), { once: true });
}
} finally {
if (import.meta.env.DEV) finishUsingConsoleFilter();
}