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:
parent
cce0894534
commit
62b0d20b97
9 changed files with 64 additions and 20 deletions
32
.changeset/new-monkeys-sit.md
Normal file
32
.changeset/new-monkeys-sit.md
Normal 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.
|
2
packages/astro/client.d.ts
vendored
2
packages/astro/client.d.ts
vendored
|
@ -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' {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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; }');
|
||||||
});
|
});
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export * from '../transitions/swap-functions.js';
|
Loading…
Reference in a new issue