0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

Extends virtual module astro:transitions/client to export swapFunctions (#11708)

* extend virtual module astro:transitions/client to exports swapFunctions

* use virtual module in e2e tests

* Update .changeset/new-monkeys-sit.md

* Update .changeset/new-monkeys-sit.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update new-monkeys-sit.md

* Update swap-functions.ts

restoreFocus() bindings are now returned by saveFocus() and do not make sense anymore as a member of the swapFunctions object

* take over suggestion

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* Update .changeset/new-monkeys-sit.md

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

---------

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
Martin Trapp 2024-08-28 13:09:49 +02:00 committed by GitHub
parent cce0894534
commit 62b0d20b97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 64 additions and 20 deletions

View file

@ -0,0 +1,32 @@
---
'astro': minor
---
Adds a new object `swapFunctions` to expose the necessary utility functions on `astro:transitions/client` that allow you to build custom swap functions to be used with view transitions.
The example below uses these functions to replace Astro's built-in default `swap` function with one that only swaps the `<main>` part of the page:
```astro
<script>
import { swapFunctions } from 'astro:transitions/client';
document.addEventListener('astro:before-swap', (e) => { e.swap = () => swapMainOnly(e.newDocument) });
function swapMainOnly(doc: Document) {
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
const newMain = doc.querySelector('main');
const oldMain = document.querySelector('main');
if (newMain && oldMain) {
swapFunctions.swapBodyElement(newMain, oldMain);
} else {
swapFunctions.swapBodyElement(doc.body, document.body);
}
restoreFocusFunction();
};
<script>
```
See the [view transitions guide](https://docs.astro.build/en/guides/view-transitions/#astrobefore-swap) for more information about hooking into the `astro:before-swap` lifecycle event and adding a custom swap implementation.

View file

@ -150,6 +150,8 @@ declare module 'astro:transitions/client' {
import('./dist/virtual-modules/transitions-events.js').TransitionBeforeSwapEvent; import('./dist/virtual-modules/transitions-events.js').TransitionBeforeSwapEvent;
export const isTransitionBeforePreparationEvent: EventModule['isTransitionBeforePreparationEvent']; export const isTransitionBeforePreparationEvent: EventModule['isTransitionBeforePreparationEvent'];
export const isTransitionBeforeSwapEvent: EventModule['isTransitionBeforeSwapEvent']; export const isTransitionBeforeSwapEvent: EventModule['isTransitionBeforeSwapEvent'];
type TransitionSwapFunctionModule = typeof import('./dist/virtual-modules/transitions-swap-functions.js');
export const swapFunctions: TransitionSwapFunctionModule['swapFunctions']
} }
declare module 'astro:prefetch' { declare module 'astro:prefetch' {

View file

@ -7,22 +7,22 @@ import Layout from '../components/Layout.astro';
</Layout> </Layout>
<script> <script>
import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from '../../node_modules/astro/dist/transitions/swap-functions' import { swapFunctions } from 'astro:transitions/client';
document.addEventListener('astro:before-swap', (e) => { document.addEventListener('astro:before-swap', (e) => {
e.swap = () => keepStyle(e.newDocument) e.swap = () => keepStyle(e.newDocument)
}); });
function keepStyle(doc: Document) { function keepStyle(doc: Document) {
deselectScripts(doc); swapFunctions.deselectScripts(doc);
swapRootAttributes(doc); swapFunctions.swapRootAttributes(doc);
{ {
const dynamicStyle = document.head.querySelector('style:not(:empty)'); const dynamicStyle = document.head.querySelector('style:not(:empty)');
swapHeadElements(doc); swapFunctions.swapHeadElements(doc);
dynamicStyle && document.head.insertAdjacentElement('afterbegin', dynamicStyle); dynamicStyle && document.head.insertAdjacentElement('afterbegin', dynamicStyle);
} }
const restoreFocusFunction = saveFocus(); const restoreFocusFunction = swapFunctions.saveFocus();
swapBodyElement(doc.body, document.body) swapFunctions.swapBodyElement(doc.body, document.body)
restoreFocusFunction(); restoreFocusFunction();
} }
</script> </script>

View file

@ -6,18 +6,18 @@ import Layout from '../components/Layout.astro';
<a id="click" href="/keep-two">go to next page</a> <a id="click" href="/keep-two">go to next page</a>
</Layout> </Layout>
<script> <script>
import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from '../../node_modules/astro/dist/transitions/swap-functions' import { swapFunctions } from 'astro:transitions/client';
function keepTheme(doc:Document) { function keepTheme(doc:Document) {
deselectScripts(doc); swapFunctions.deselectScripts(doc);
{ {
const theme = document.documentElement.getAttribute('data-theme')!; const theme = document.documentElement.getAttribute('data-theme')!;
swapRootAttributes(doc); swapFunctions.swapRootAttributes(doc);
document.documentElement.setAttribute('data-theme', theme); document.documentElement.setAttribute('data-theme', theme);
} }
swapHeadElements(doc); swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = saveFocus(); const restoreFocusFunction = swapFunctions.saveFocus();
swapBodyElement(doc.body, document.body) swapFunctions.swapBodyElement(doc.body, document.body)
restoreFocusFunction(); restoreFocusFunction();
} }

View file

@ -9,24 +9,24 @@ import Layout from '../components/Layout.astro';
<a id="click" href="/keep-two">go to next page</a> <a id="click" href="/keep-two">go to next page</a>
</Layout> </Layout>
<script> <script>
import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from "../../node_modules/astro/dist/transitions/swap-functions" import { swapFunctions } from 'astro:transitions/client';
document.addEventListener('astro:before-swap', (e) => { document.addEventListener('astro:before-swap', (e) => {
e.swap = () => replaceMain(e.newDocument) e.swap = () => replaceMain(e.newDocument)
}); });
function replaceMain(doc:Document){ function replaceMain(doc:Document){
deselectScripts(doc); swapFunctions.deselectScripts(doc);
swapRootAttributes(doc); swapFunctions.swapRootAttributes(doc);
swapHeadElements(doc); swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = saveFocus(); const restoreFocusFunction = swapFunctions.saveFocus();
{ {
const newMain = doc.body.querySelector('main section'); const newMain = doc.body.querySelector('main section');
const oldMain = document.body.querySelector('main section'); const oldMain = document.body.querySelector('main section');
if (newMain && oldMain) { if (newMain && oldMain) {
swapBodyElement(newMain, oldMain); swapFunctions.swapBodyElement(newMain, oldMain);
} else { } else {
swapBodyElement(doc.body, document.body); swapFunctions.swapBodyElement(doc.body, document.body);
} }
} }
restoreFocusFunction(); restoreFocusFunction();

View file

@ -1447,7 +1447,7 @@ test.describe('View Transitions', () => {
await page.click('#click'); await page.click('#click');
await expect(page.locator('#name'), 'should have content').toHaveText('Keep 2'); await expect(page.locator('#name'), 'should have content').toHaveText('Keep 2');
const styleElement = await page.$('head > style'); const styleElement = await page.$('head > style:nth-child(1)');
const styleContent = await page.evaluate((style) => style.innerHTML, styleElement); const styleContent = await page.evaluate((style) => style.innerHTML, styleElement);
expect(styleContent).toBe('body { background-color: purple; }'); expect(styleContent).toBe('body { background-color: purple; }');
}); });

View file

@ -133,6 +133,14 @@ const shouldCopyProps = (el: HTMLElement): boolean => {
return persistProps == null || persistProps === 'false'; return persistProps == null || persistProps === 'false';
}; };
export const swapFunctions = {
deselectScripts,
swapRootAttributes,
swapHeadElements,
swapBodyElement,
saveFocus,
};
export const swap = (doc: Document) => { export const swap = (doc: Document) => {
deselectScripts(doc); deselectScripts(doc);
swapRootAttributes(doc); swapRootAttributes(doc);

View file

@ -42,6 +42,7 @@ export default function astroTransitions({ settings }: { settings: AstroSettings
TRANSITION_BEFORE_SWAP, isTransitionBeforeSwapEvent, TransitionBeforeSwapEvent, TRANSITION_BEFORE_SWAP, isTransitionBeforeSwapEvent, TransitionBeforeSwapEvent,
TRANSITION_AFTER_SWAP, TRANSITION_PAGE_LOAD TRANSITION_AFTER_SWAP, TRANSITION_PAGE_LOAD
} from "astro/virtual-modules/transitions-events.js"; } from "astro/virtual-modules/transitions-events.js";
export { swapFunctions } from "astro/virtual-modules/transitions-swap-functions.js";
`; `;
} }
}, },

View file

@ -0,0 +1 @@
export * from '../transitions/swap-functions.js';