diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index 100ee43bd..f94383f4d 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -7,8 +7,9 @@ export interface Props { const { fallback = 'animate' } = Astro.props as Props; --- - - + + + diff --git a/packages/astro/components/viewtransitions.css b/packages/astro/components/viewtransitions.css index 296c97c2b..3b6733182 100644 --- a/packages/astro/components/viewtransitions.css +++ b/packages/astro/components/viewtransitions.css @@ -8,25 +8,37 @@ } @keyframes astroFadeIn { - from { opacity: 0; } + from { + opacity: 0; + } } @keyframes astroFadeOut { - to { opacity: 0; } + to { + opacity: 0; + } } @keyframes astroSlideFromRight { - from { transform: translateX(100%); } + from { + transform: translateX(100%); + } } @keyframes astroSlideFromLeft { - from { transform: translateX(-100%); } + from { + transform: translateX(-100%); + } } @keyframes astroSlideToRight { - to { transform: translateX(100%); } + to { + transform: translateX(100%); + } } @keyframes astroSlideToLeft { - to { transform: translateX(-100%); } + to { + transform: translateX(-100%); + } } diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index 474424182..f42e21d12 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -16,7 +16,7 @@ test.afterAll(async () => { test.describe('View Transitions', () => { test('Moving from page 1 to page 2', async ({ page, astro }) => { const loads = []; - page.addListener('load', p => { + page.addListener('load', (p) => { loads.push(p.title()); }); @@ -35,7 +35,7 @@ test.describe('View Transitions', () => { test('Back button is captured', async ({ page, astro }) => { const loads = []; - page.addListener('load', p => { + page.addListener('load', (p) => { loads.push(p.title()); }); @@ -59,7 +59,7 @@ test.describe('View Transitions', () => { test('Clicking on a link with nested content', async ({ page, astro }) => { const loads = []; - page.addListener('load', p => { + page.addListener('load', (p) => { loads.push(p.title()); }); @@ -76,9 +76,12 @@ test.describe('View Transitions', () => { expect(loads.length, 'There should only be 1 page load').toEqual(1); }); - test('Moving from a page without ViewTransitions triggers a full page navigation', async ({ page, astro }) => { + test('Moving from a page without ViewTransitions triggers a full page navigation', async ({ + page, + astro, + }) => { const loads = []; - page.addListener('load', p => { + page.addListener('load', (p) => { loads.push(p.title()); }); @@ -96,6 +99,9 @@ test.describe('View Transitions', () => { p = page.locator('#two'); await expect(p, 'should have content').toHaveText('Page 2'); - expect(loads.length, 'There should be 2 page loads. The original, then going from 3 to 2').toEqual(2); + expect( + loads.length, + 'There should be 2 page loads. The original, then going from 3 to 2' + ).toEqual(2); }); }); diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 3c171822c..cab483b77 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -56,10 +56,10 @@ export interface AstroBuiltinProps { } export interface TransitionAnimation { - name: string; // The name of the keyframe - delay?: number | string; - duration?: number | string; - easing?: string; + name: string; // The name of the keyframe + delay?: number | string; + duration?: number | string; + easing?: string; fillMode?: string; direction?: string; } @@ -1270,7 +1270,7 @@ export interface AstroUserConfig { * } * ``` */ - viewTransitions?: boolean; + viewTransitions?: boolean; }; // Legacy options to be removed diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index 99c839a6d..34c1e5549 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -233,7 +233,10 @@ export const AstroConfigSchema = z.object({ experimental: z .object({ assets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.assets), - viewTransitions: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.viewTransitions), + viewTransitions: z + .boolean() + .optional() + .default(ASTRO_CONFIG_DEFAULTS.experimental.viewTransitions), }) .passthrough() .refine( diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 658648e3e..c0b989b77 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -11,6 +11,7 @@ import { astroContentImportPlugin, astroContentVirtualModPlugin, } from '../content/index.js'; +import astroTransitions from '../transitions/vite-plugin-transitions.js'; import astroPostprocessVitePlugin from '../vite-plugin-astro-postprocess/index.js'; import { vitePluginAstroServer } from '../vite-plugin-astro-server/index.js'; import astroVitePlugin from '../vite-plugin-astro/index.js'; @@ -27,7 +28,6 @@ import astroScannerPlugin from '../vite-plugin-scanner/index.js'; import astroScriptsPlugin from '../vite-plugin-scripts/index.js'; import astroScriptsPageSSRPlugin from '../vite-plugin-scripts/page-ssr.js'; import { vitePluginSSRManifest } from '../vite-plugin-ssr-manifest/index.js'; -import astroTransitions from '../transitions/vite-plugin-transitions.js'; import { joinPaths } from './path.js'; interface CreateViteOptions { diff --git a/packages/astro/src/runtime/server/astro-component.ts b/packages/astro/src/runtime/server/astro-component.ts index aa205d790..57f2d3c3b 100644 --- a/packages/astro/src/runtime/server/astro-component.ts +++ b/packages/astro/src/runtime/server/astro-component.ts @@ -7,7 +7,11 @@ function validateArgs(args: unknown[]): args is Parameters) => { if (!validateArgs(args)) { @@ -40,7 +44,7 @@ function createComponentWithOptions(opts: CreateComponentOptions) { export function createComponent( arg1: AstroComponentFactory | CreateComponentOptions, moduleId?: string, - propagation?: PropagationHint, + propagation?: PropagationHint ) { if (typeof arg1 === 'function') { return baseCreateComponent(arg1, moduleId, propagation); diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 08a205e05..4670a3e87 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -33,13 +33,13 @@ export { stringifyChunk, voidElementNames, } from './render/index.js'; -export { renderTransition } from './transition.js'; export type { AstroComponentFactory, AstroComponentInstance, ComponentSlots, RenderInstruction, } from './render/index.js'; +export { renderTransition } from './transition.js'; import { markHTMLString } from './escape.js'; import { addAttribute, Renderer } from './render/index.js'; diff --git a/packages/astro/src/runtime/server/transition.ts b/packages/astro/src/runtime/server/transition.ts index 98149e38a..253a861f9 100644 --- a/packages/astro/src/runtime/server/transition.ts +++ b/packages/astro/src/runtime/server/transition.ts @@ -1,16 +1,16 @@ import type { SSRResult, TransitionAnimation, - TransitionDirectionalAnimations, TransitionAnimationValue, + TransitionDirectionalAnimations, } from '../../@types/astro'; +import { fade, slide } from '../../transitions/index.js'; import { markHTMLString } from './escape.js'; -import { slide, fade } from '../../transitions/index.js'; const transitionNameMap = new WeakMap(); function incrementTransitionNumber(result: SSRResult) { let num = 1; - if(transitionNameMap.has(result)) { + if (transitionNameMap.has(result)) { num = transitionNameMap.get(result)! + 1; } transitionNameMap.set(result, num); @@ -21,9 +21,14 @@ function createTransitionScope(result: SSRResult, hash: string) { const num = incrementTransitionNumber(result); return `astro-${hash}-${num}`; } -export function renderTransition(result: SSRResult, hash: string, animationName: TransitionAnimationValue | undefined, transitionName: string) { +export function renderTransition( + result: SSRResult, + hash: string, + animationName: TransitionAnimationValue | undefined, + transitionName: string +) { let animations: TransitionDirectionalAnimations | null = null; - switch(animationName) { + switch (animationName) { case 'fade': { animations = fade(); break; @@ -33,7 +38,7 @@ export function renderTransition(result: SSRResult, hash: string, animationName: break; } default: { - if(typeof animationName === 'object') { + if (typeof animationName === 'object') { animations = animationName; } } @@ -42,16 +47,18 @@ export function renderTransition(result: SSRResult, hash: string, animationName: const scope = createTransitionScope(result, hash); // Default transition name is the scope of the element, ie HASH-1 - if(!transitionName) { + if (!transitionName) { transitionName = scope; } const styles = markHTMLString(``) + `.trim() + } + `); result._metadata.extraHead.push(styles); @@ -89,12 +97,12 @@ export function renderTransition(result: SSRResult, hash: string, animationName: type AnimationBuilder = { toString(): string; - [key: string]: string[] | ((k: string) => string); -} + [key: string]: string[] | ((k: string) => string); +}; function addAnimationProperty(builder: AnimationBuilder, prop: string, value: string | number) { let arr = builder[prop]; - if(Array.isArray(arr)) { + if (Array.isArray(arr)) { arr.push(value.toString()); } else { builder[prop] = [value.toString()]; @@ -105,19 +113,19 @@ function animationBuilder(): AnimationBuilder { return { toString() { let out = ''; - for(let k in this) { + for (let k in this) { let value = this[k]; - if(Array.isArray(value)) { - out += `\n\t${k}: ${value.join(', ')};` + if (Array.isArray(value)) { + out += `\n\t${k}: ${value.join(', ')};`; } } return out; - } + }, }; } function stringifyAnimation(anim: TransitionAnimation | TransitionAnimation[]): string { - if(Array.isArray(anim)) { + if (Array.isArray(anim)) { return stringifyAnimations(anim); } else { return stringifyAnimations([anim]); @@ -127,26 +135,26 @@ function stringifyAnimation(anim: TransitionAnimation | TransitionAnimation[]): function stringifyAnimations(anims: TransitionAnimation[]): string { const builder = animationBuilder(); - for(const anim of anims) { + for (const anim of anims) { /*300ms cubic-bezier(0.4, 0, 0.2, 1) both astroSlideFromRight;*/ - if(anim.duration) { + if (anim.duration) { addAnimationProperty(builder, 'animation-duration', toTimeValue(anim.duration)); } - if(anim.easing) { + if (anim.easing) { addAnimationProperty(builder, 'animation-timing-function', anim.easing); } - if(anim.direction) { + if (anim.direction) { addAnimationProperty(builder, 'animation-direction', anim.direction); } - if(anim.delay) { + if (anim.delay) { addAnimationProperty(builder, 'animation-delay', anim.delay); } - if(anim.fillMode) { + if (anim.fillMode) { addAnimationProperty(builder, 'animation-fill-mode', anim.fillMode); } addAnimationProperty(builder, 'animation-name', anim.name); } - + return builder.toString(); } diff --git a/packages/astro/src/transitions/index.ts b/packages/astro/src/transitions/index.ts index d8dbb4e3b..4514269e5 100644 --- a/packages/astro/src/transitions/index.ts +++ b/packages/astro/src/transitions/index.ts @@ -1,45 +1,51 @@ -import type { TransitionDirectionalAnimations, TransitionAnimationPair } from '../@types/astro'; +import type { TransitionDirectionalAnimations } from '../@types/astro'; export function slide({ - duration + duration, }: { duration?: string | number; } = {}): TransitionDirectionalAnimations { return { forwards: { - old: [{ - name: 'astroFadeOut', - duration: duration ?? '90ms', - easing: 'cubic-bezier(0.4, 0, 1, 1)', - fillMode: 'both' - }, { - name: 'astroSlideToLeft', - duration: duration ?? '300ms', - easing: 'cubic-bezier(0.4, 0, 0.2, 1)', - fillMode: 'both' - }], - new: [{ - name: 'astroFadeIn', - duration: duration ?? '210ms', - easing: 'cubic-bezier(0, 0, 0.2, 1)', - delay: '90ms', - fillMode: 'both' - }, { - name: 'astroSlideFromRight', - duration: duration ?? '300ms', - easing: 'cubic-bezier(0.4, 0, 0.2, 1)', - fillMode: 'both' - }] + old: [ + { + name: 'astroFadeOut', + duration: duration ?? '90ms', + easing: 'cubic-bezier(0.4, 0, 1, 1)', + fillMode: 'both', + }, + { + name: 'astroSlideToLeft', + duration: duration ?? '300ms', + easing: 'cubic-bezier(0.4, 0, 0.2, 1)', + fillMode: 'both', + }, + ], + new: [ + { + name: 'astroFadeIn', + duration: duration ?? '210ms', + easing: 'cubic-bezier(0, 0, 0.2, 1)', + delay: '90ms', + fillMode: 'both', + }, + { + name: 'astroSlideFromRight', + duration: duration ?? '300ms', + easing: 'cubic-bezier(0.4, 0, 0.2, 1)', + fillMode: 'both', + }, + ], }, backwards: { old: [{ name: 'astroFadeOut' }, { name: 'astroSlideToRight' }], - new: [{ name: 'astroFadeIn' }, { name: 'astroSlideFromLeft' }] - } + new: [{ name: 'astroFadeIn' }, { name: 'astroSlideFromLeft' }], + }, }; } export function fade({ - duration + duration, }: { duration?: string | number; } = {}): TransitionDirectionalAnimations { @@ -55,7 +61,7 @@ export function fade({ duration: duration ?? '0.3s', easing: 'linear', fillMode: 'backwards', - } + }, } satisfies TransitionAnimationPair; return { diff --git a/packages/astro/src/transitions/vite-plugin-transitions.ts b/packages/astro/src/transitions/vite-plugin-transitions.ts index 891d5a22f..9803be211 100644 --- a/packages/astro/src/transitions/vite-plugin-transitions.ts +++ b/packages/astro/src/transitions/vite-plugin-transitions.ts @@ -1,12 +1,12 @@ -import type { AstroConfig } from '../@types/astro'; import * as vite from 'vite'; +import type { AstroConfig } from '../@types/astro'; import { AstroError } from '../core/errors/index.js'; const virtualModuleId = 'astro:transitions'; const resolvedVirtualModuleId = '\0' + virtualModuleId; // The virtual module for the astro:transitions namespace -export default function astroTransitions({ config }: { config: AstroConfig; }): vite.Plugin { +export default function astroTransitions({ config }: { config: AstroConfig }): vite.Plugin { return { name: 'astro:transitions', async resolveId(id) { @@ -16,7 +16,7 @@ export default function astroTransitions({ config }: { config: AstroConfig; }): }, load(id) { if (id === resolvedVirtualModuleId) { - if(!config.experimental.viewTransitions) { + if (!config.experimental.viewTransitions) { throw new AstroError({ title: 'Experimental View Transitions not enabled', message: `View Transitions support is experimental. To enable update your config to include: @@ -25,7 +25,7 @@ export default defineConfig({ experimental: { viewTransitions: true } -})` +})`, }); } diff --git a/packages/astro/test/units/compile/invalid-css.test.js b/packages/astro/test/units/compile/invalid-css.test.js index db892b5bf..7a0303437 100644 --- a/packages/astro/test/units/compile/invalid-css.test.js +++ b/packages/astro/test/units/compile/invalid-css.test.js @@ -12,7 +12,7 @@ describe('astro/src/core/compile', () => { await cachedCompilation({ astroConfig: { root: pathToFileURL('/'), - experimental: {} + experimental: {}, }, viteConfig: await resolveConfig({ configFile: false }, 'serve'), filename: '/src/pages/index.astro',