diff --git a/.changeset/silly-garlics-live.md b/.changeset/silly-garlics-live.md new file mode 100644 index 000000000000..d019b892ce07 --- /dev/null +++ b/.changeset/silly-garlics-live.md @@ -0,0 +1,62 @@ +--- +'astro': minor +--- + +Built-in View Transitions Support (experimental) + +Astro now supports [view transitions](https://developer.chrome.com/docs/web-platform/view-transitions/) through the new `` component and the `transition:animate` (and associated) directives. View transitions are a great fit for content-oriented sites, and we see it as the best path to get the benefits of client-side routing (smoother transitions) without sacrificing the more simple mental model of MPAs. + +Enable support for view transitions in Astro 2.9 by adding the experimental flag to your config: + +```js +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + experimental: { + viewTransitions: true, + }, +}) +``` + +This enables you to use the new APIs added. + +#### + +This is a component which acts as the *router* for transitions between pages. Add it to the `` section of each individual page where transitions should occur *in the client* as you navigate away to another page, instead of causing a full page browser refresh. To enable support throughout your entire app, add the component in some common layout or component that targets the `` of every page. + +__CommonHead.astro__ + +```astro +--- +import { ViewTransitions } from 'astro:transitions'; +--- + + +{Astro.props.title} + +``` + +With only this change, your app will now route completely in-client. You can then add transitions to individual elements using the `transition:animate` directive. + +#### Animations + +Add `transition:animate` to any element to use Astro's built-in animations. + +```astro +
+``` + +In the above, Astro's `slide` animation will cause the `
` element to slide out to the left, and then slide in from the right when you navigate away from the page. + +You can also customize these animations using any CSS animation properties, for example, by specifying a duration: + +```astro +--- +import { slide } from 'astro:transition'; +--- +
+``` + +#### Continue learning + +Check out the [client-side routing docs](https://docs.astro.build/en/guides/client-side-routing/) to learn more. diff --git a/examples/basics/src/layouts/Layout.astro b/examples/basics/src/layouts/Layout.astro index 39e868100901..9b9de105c400 100644 --- a/examples/basics/src/layouts/Layout.astro +++ b/examples/basics/src/layouts/Layout.astro @@ -1,4 +1,4 @@ ---- +--- interface Props { title: string; } diff --git a/examples/portfolio/src/components/MainHead.astro b/examples/portfolio/src/components/MainHead.astro index 93f1e7bdb26e..b4c7263ff5aa 100644 --- a/examples/portfolio/src/components/MainHead.astro +++ b/examples/portfolio/src/components/MainHead.astro @@ -25,7 +25,6 @@ const { href="https://fonts.googleapis.com/css2?family=Public+Sans:ital,wght@0,400;0,700;1,400&family=Rubik:wght@500;600&display=swap" rel="stylesheet" /> - diff --git a/packages/astro/components/index.ts b/packages/astro/components/index.ts index 864c7cc3bbdf..6bd537087eee 100644 --- a/packages/astro/components/index.ts +++ b/packages/astro/components/index.ts @@ -1,2 +1,3 @@ export { default as Code } from './Code.astro'; export { default as Debug } from './Debug.astro'; +export { default as ViewTransitions } from './ViewTransitions.astro'; diff --git a/packages/astro/components/viewtransitions.css b/packages/astro/components/viewtransitions.css new file mode 100644 index 000000000000..296c97c2b697 --- /dev/null +++ b/packages/astro/components/viewtransitions.css @@ -0,0 +1,32 @@ +@keyframes astroFadeInOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes astroFadeIn { + from { opacity: 0; } +} + +@keyframes astroFadeOut { + to { opacity: 0; } +} + +@keyframes astroSlideFromRight { + from { transform: translateX(100%); } +} + +@keyframes astroSlideFromLeft { + from { transform: translateX(-100%); } +} + +@keyframes astroSlideToRight { + to { transform: translateX(100%); } +} + +@keyframes astroSlideToLeft { + to { transform: translateX(-100%); } +} diff --git a/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs b/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs new file mode 100644 index 000000000000..50ba5b32c61d --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({ + experimental: { + viewTransitions: true, + }, +}); diff --git a/packages/astro/e2e/fixtures/view-transitions/package.json b/packages/astro/e2e/fixtures/view-transitions/package.json new file mode 100644 index 000000000000..50258fd1a16b --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/package.json @@ -0,0 +1,8 @@ +{ + "name": "@e2e/view-transitions", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro new file mode 100644 index 000000000000..38bc302e92e2 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro @@ -0,0 +1,17 @@ +--- +import { ViewTransitions } from 'astro:transitions'; +--- + + + Testing + + + +
+

testing

+
+
+ +
+ + diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/four.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/four.astro new file mode 100644 index 000000000000..e322937935c0 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/four.astro @@ -0,0 +1,12 @@ +--- +import Layout from '../components/Layout.astro'; +--- + +

Page 4

+ +
+ Nested + go to 1 +
+
+
diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro new file mode 100644 index 000000000000..e896a857281a --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro @@ -0,0 +1,8 @@ +--- +import Layout from '../components/Layout.astro'; +--- + +

Page 1

+ go to 2 + go to 3 +
diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/three.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/three.astro new file mode 100644 index 000000000000..676e8b61be96 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/three.astro @@ -0,0 +1,11 @@ + + + Page 3 + + +
+

Page 3

+ go to 2 +
+ + diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro new file mode 100644 index 000000000000..b3cadcad7b71 --- /dev/null +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/two.astro @@ -0,0 +1,6 @@ +--- +import Layout from '../components/Layout.astro'; +--- + +

Page 2

+
diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js new file mode 100644 index 000000000000..4744241820c7 --- /dev/null +++ b/packages/astro/e2e/view-transitions.test.js @@ -0,0 +1,101 @@ +import { expect } from '@playwright/test'; +import { testFactory } from './test-utils.js'; + +const test = testFactory({ root: './fixtures/view-transitions/' }); + +let devServer; + +test.beforeAll(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterAll(async () => { + await devServer.stop(); +}); + +test.describe('View Transitions', () => { + test('Moving from page 1 to page 2', async ({ page, astro }) => { + const loads = []; + page.addListener('load', p => { + loads.push(p.title()); + }); + + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + let p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // go to page 2 + await page.click('#click-two'); + p = page.locator('#two'); + await expect(p, 'should have content').toHaveText('Page 2'); + + expect(loads.length, 'There should only be 1 page load').toEqual(1); + }); + + test('Back button is captured', async ({ page, astro }) => { + const loads = []; + page.addListener('load', p => { + loads.push(p.title()); + }); + + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + let p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // go to page 2 + await page.click('#click-two'); + p = page.locator('#two'); + await expect(p, 'should have content').toHaveText('Page 2'); + + // Back to page 1 + await page.goBack(); + p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + expect(loads.length, 'There should only be 1 page load').toEqual(1); + }); + + test('Clicking on a link with nested content', async ({ page, astro }) => { + const loads = []; + page.addListener('load', p => { + loads.push(p.title()); + }); + + // Go to page 4 + await page.goto(astro.resolveUrl('/four')); + let p = page.locator('#four'); + await expect(p, 'should have content').toHaveText('Page 4'); + + // Go to page 1 + await page.click('#click-one'); + p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + 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 }) => { + const loads = []; + page.addListener('load', p => { + loads.push(p.title()); + }); + + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + let p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // Go to page 3 which does *not* have ViewTransitions enabled + await page.click('#click-three'); + p = page.locator('#three'); + await expect(p, 'should have content').toHaveText('Page 3'); + + await page.click('#click-two'); + 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); + }); +}); diff --git a/packages/astro/package.json b/packages/astro/package.json index 85b4bb19cb18..14bd76757efb 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -71,7 +71,8 @@ "./middleware": { "types": "./dist/core/middleware/index.d.ts", "default": "./dist/core/middleware/index.js" - } + }, + "./transitions": "./dist/transitions/index.js" }, "imports": { "#astro/*": "./dist/*.js" @@ -114,7 +115,7 @@ "test:e2e:match": "playwright test -g" }, "dependencies": { - "@astrojs/compiler": "^1.5.3", + "@astrojs/compiler": "^1.6.0", "@astrojs/internal-helpers": "^0.1.1", "@astrojs/language-server": "^1.0.0", "@astrojs/markdown-remark": "^2.2.1", @@ -127,6 +128,7 @@ "@babel/traverse": "^7.22.5", "@babel/types": "^7.22.5", "@types/babel__core": "^7.20.1", + "@types/dom-view-transitions": "^1.0.1", "@types/yargs-parser": "^21.0.0", "acorn": "^8.9.0", "boxen": "^6.2.1", @@ -150,6 +152,7 @@ "kleur": "^4.1.4", "magic-string": "^0.27.0", "mime": "^3.0.0", + "network-information-types": "^0.1.1", "ora": "^6.3.1", "p-limit": "^4.0.0", "path-to-regexp": "^6.2.1", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 0a972d4b07f3..3c171822cc97 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -55,6 +55,27 @@ export interface AstroBuiltinProps { 'client:only'?: boolean | string; } +export interface TransitionAnimation { + name: string; // The name of the keyframe + delay?: number | string; + duration?: number | string; + easing?: string; + fillMode?: string; + direction?: string; +} + +export interface TransitionAnimationPair { + old: TransitionAnimation | TransitionAnimation[]; + new: TransitionAnimation | TransitionAnimation[]; +} + +export interface TransitionDirectionalAnimations { + forwards: TransitionAnimationPair; + backwards: TransitionAnimationPair; +} + +export type TransitionAnimationValue = 'morph' | 'slide' | 'fade' | TransitionDirectionalAnimations; + // Allow users to extend this for astro-jsx.d.ts // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface AstroClientDirectives {} @@ -69,6 +90,8 @@ export interface AstroBuiltinAttributes { 'set:html'?: any; 'set:text'?: any; 'is:raw'?: boolean; + 'transition:animate'?: 'morph' | 'slide' | 'fade' | TransitionDirectionalAnimations; + 'transition:name'?: string; } export interface AstroDefineVarsAttribute { @@ -1227,6 +1250,27 @@ export interface AstroUserConfig { * ``` */ assets?: boolean; + + /** + * @docs + * @name experimental.viewTransitions + * @type {boolean} + * @default `false` + * @version 2.9.0 + * @description + * Enable experimental support for the `` component. With this enabled + * you can opt-in to [client-side routing](https://docs.astro.build/en/guides/client-side-routing/) on a per-page basis using this component + * and enable animations with the `transition:animate` directive. + * + * ```js + * { + * experimental: { + * viewTransitions: true, + * }, + * } + * ``` + */ + viewTransitions?: boolean; }; // Legacy options to be removed diff --git a/packages/astro/src/core/compile/compile.ts b/packages/astro/src/core/compile/compile.ts index a0bc79c72df3..c1df9e5f3e62 100644 --- a/packages/astro/src/core/compile/compile.ts +++ b/packages/astro/src/core/compile/compile.ts @@ -45,6 +45,8 @@ export async function compile({ astroGlobalArgs: JSON.stringify(astroConfig.site), scopedStyleStrategy: astroConfig.scopedStyleStrategy, resultScopedSlot: true, + experimentalTransitions: astroConfig.experimental.viewTransitions, + transitionsAnimationURL: 'astro/components/viewtransitions.css', preprocessStyle: createStylePreprocessor({ filename, viteConfig, diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index 7a27f1abea21..99c839a6dde7 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -45,6 +45,7 @@ const ASTRO_CONFIG_DEFAULTS = { redirects: {}, experimental: { assets: false, + viewTransitions: false, }, } satisfies AstroUserConfig & { server: { open: boolean } }; @@ -232,6 +233,7 @@ 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), }) .passthrough() .refine( diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 52b5fd277a40..658648e3eefd 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -27,6 +27,7 @@ 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 { @@ -132,6 +133,7 @@ export async function createVite( astroContentAssetPropagationPlugin({ mode, settings }), vitePluginSSRManifest(), settings.config.experimental.assets ? [astroAssetsPlugin({ settings, logging, mode })] : [], + astroTransitions({ config: settings.config }), ], publicDir: fileURLToPath(settings.config.publicDir), root: fileURLToPath(settings.config.root), diff --git a/packages/astro/src/runtime/server/astro-component.ts b/packages/astro/src/runtime/server/astro-component.ts index 44428b9295ad..aa205d790880 100644 --- a/packages/astro/src/runtime/server/astro-component.ts +++ b/packages/astro/src/runtime/server/astro-component.ts @@ -7,7 +7,7 @@ function validateArgs(args: unknown[]): args is Parameters) => { if (!validateArgs(args)) { @@ -22,6 +22,7 @@ function baseCreateComponent(cb: AstroComponentFactory, moduleId?: string): Astr // Add a flag to this callback to mark it as an Astro component fn.isAstroComponentFactory = true; fn.moduleId = moduleId; + fn.propagation = propagation; return fn; } @@ -32,17 +33,17 @@ interface CreateComponentOptions { } function createComponentWithOptions(opts: CreateComponentOptions) { - const cb = baseCreateComponent(opts.factory, opts.moduleId); - cb.propagation = opts.propagation; + const cb = baseCreateComponent(opts.factory, opts.moduleId, opts.propagation); return cb; } // Used in creating the component. aka the main export. export function createComponent( arg1: AstroComponentFactory | CreateComponentOptions, - moduleId?: string + moduleId?: string, + propagation?: PropagationHint, ) { if (typeof arg1 === 'function') { - return baseCreateComponent(arg1, moduleId); + return baseCreateComponent(arg1, moduleId, propagation); } else { return createComponentWithOptions(arg1); } diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 564ebbe91814..08a205e058ea 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -33,6 +33,7 @@ export { stringifyChunk, voidElementNames, } from './render/index.js'; +export { renderTransition } from './transition.js'; export type { AstroComponentFactory, AstroComponentInstance, diff --git a/packages/astro/src/runtime/server/transition.ts b/packages/astro/src/runtime/server/transition.ts new file mode 100644 index 000000000000..98149e38a78b --- /dev/null +++ b/packages/astro/src/runtime/server/transition.ts @@ -0,0 +1,155 @@ +import type { + SSRResult, + TransitionAnimation, + TransitionDirectionalAnimations, + TransitionAnimationValue, +} from '../../@types/astro'; +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)) { + num = transitionNameMap.get(result)! + 1; + } + transitionNameMap.set(result, num); + return num; +} + +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) { + let animations: TransitionDirectionalAnimations | null = null; + switch(animationName) { + case 'fade': { + animations = fade(); + break; + } + case 'slide': { + animations = slide(); + break; + } + default: { + if(typeof animationName === 'object') { + animations = animationName; + } + } + } + + const scope = createTransitionScope(result, hash); + + // Default transition name is the scope of the element, ie HASH-1 + if(!transitionName) { + transitionName = scope; + } + + const styles = markHTMLString(``) + + result._metadata.extraHead.push(styles); + + return scope; +} + +type AnimationBuilder = { + toString(): string; + [key: string]: string[] | ((k: string) => string); +} + +function addAnimationProperty(builder: AnimationBuilder, prop: string, value: string | number) { + let arr = builder[prop]; + if(Array.isArray(arr)) { + arr.push(value.toString()); + } else { + builder[prop] = [value.toString()]; + } +} + +function animationBuilder(): AnimationBuilder { + return { + toString() { + let out = ''; + for(let k in this) { + let value = this[k]; + if(Array.isArray(value)) { + out += `\n\t${k}: ${value.join(', ')};` + } + } + return out; + } + }; +} + +function stringifyAnimation(anim: TransitionAnimation | TransitionAnimation[]): string { + if(Array.isArray(anim)) { + return stringifyAnimations(anim); + } else { + return stringifyAnimations([anim]); + } +} + +function stringifyAnimations(anims: TransitionAnimation[]): string { + const builder = animationBuilder(); + + for(const anim of anims) { + /*300ms cubic-bezier(0.4, 0, 0.2, 1) both astroSlideFromRight;*/ + if(anim.duration) { + addAnimationProperty(builder, 'animation-duration', toTimeValue(anim.duration)); + } + if(anim.easing) { + addAnimationProperty(builder, 'animation-timing-function', anim.easing); + } + if(anim.direction) { + addAnimationProperty(builder, 'animation-direction', anim.direction); + } + if(anim.delay) { + addAnimationProperty(builder, 'animation-delay', anim.delay); + } + if(anim.fillMode) { + addAnimationProperty(builder, 'animation-fill-mode', anim.fillMode); + } + addAnimationProperty(builder, 'animation-name', anim.name); + } + + return builder.toString(); +} + +function toTimeValue(num: number | string) { + return typeof num === 'number' ? num + 'ms' : num; +} diff --git a/packages/astro/src/transitions/index.ts b/packages/astro/src/transitions/index.ts new file mode 100644 index 000000000000..d8dbb4e3bde7 --- /dev/null +++ b/packages/astro/src/transitions/index.ts @@ -0,0 +1,65 @@ +import type { TransitionDirectionalAnimations, TransitionAnimationPair } from '../@types/astro'; + +export function slide({ + 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' + }] + }, + backwards: { + old: [{ name: 'astroFadeOut' }, { name: 'astroSlideToRight' }], + new: [{ name: 'astroFadeIn' }, { name: 'astroSlideFromLeft' }] + } + }; +} + +export function fade({ + duration +}: { + duration?: string | number; +} = {}): TransitionDirectionalAnimations { + const anim = { + old: { + name: 'astroFadeInOut', + duration: duration ?? '0.2s', + easing: 'linear', + fillMode: 'forwards', + }, + new: { + name: 'astroFadeInOut', + duration: duration ?? '0.3s', + easing: 'linear', + fillMode: 'backwards', + } + } satisfies TransitionAnimationPair; + + return { + forwards: anim, + backwards: anim, + }; +} diff --git a/packages/astro/src/transitions/vite-plugin-transitions.ts b/packages/astro/src/transitions/vite-plugin-transitions.ts new file mode 100644 index 000000000000..891d5a22fb0b --- /dev/null +++ b/packages/astro/src/transitions/vite-plugin-transitions.ts @@ -0,0 +1,39 @@ +import type { AstroConfig } from '../@types/astro'; +import * as vite from 'vite'; +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 { + return { + name: 'astro:transitions', + async resolveId(id) { + if (id === virtualModuleId) { + return resolvedVirtualModuleId; + } + }, + load(id) { + if (id === resolvedVirtualModuleId) { + 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: + +export default defineConfig({ + experimental: { + viewTransitions: true + } +})` + }); + } + + return ` + export * from "astro/transitions"; + export { default as ViewTransitions } from "astro/components/ViewTransitions.astro"; + `; + } + }, + }; +} diff --git a/packages/astro/test/units/compile/invalid-css.test.js b/packages/astro/test/units/compile/invalid-css.test.js index d52b66c92ca0..db892b5bf309 100644 --- a/packages/astro/test/units/compile/invalid-css.test.js +++ b/packages/astro/test/units/compile/invalid-css.test.js @@ -12,6 +12,7 @@ describe('astro/src/core/compile', () => { await cachedCompilation({ astroConfig: { root: pathToFileURL('/'), + experimental: {} }, viteConfig: await resolveConfig({ configFile: false }, 'serve'), filename: '/src/pages/index.astro', diff --git a/packages/astro/test/units/vite-plugin-astro/compile.test.js b/packages/astro/test/units/vite-plugin-astro/compile.test.js index 02a88855ea15..5fa87433eb90 100644 --- a/packages/astro/test/units/vite-plugin-astro/compile.test.js +++ b/packages/astro/test/units/vite-plugin-astro/compile.test.js @@ -13,7 +13,7 @@ const viteConfig = await resolveConfig({ configFile: false }, 'serve'); async function compile(source, id) { return await cachedFullCompilation({ compileProps: { - astroConfig: { root: pathToFileURL('/'), base: '/' }, + astroConfig: { root: pathToFileURL('/'), base: '/', experimental: {} }, viteConfig, filename: id, source, diff --git a/packages/astro/tsconfig.json b/packages/astro/tsconfig.json index 23ac0c78b62b..839239eafa22 100644 --- a/packages/astro/tsconfig.json +++ b/packages/astro/tsconfig.json @@ -6,6 +6,8 @@ "declarationDir": "./dist", "module": "ES2022", "outDir": "./dist", - "target": "ES2021" + "target": "ES2021", + "jsx": "preserve", + "types": ["@types/dom-view-transitions", "network-information-types"] } } diff --git a/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs b/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs index e386f5e21d08..1b53c53a8ca1 100644 --- a/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs +++ b/packages/integrations/sitemap/test/fixtures/static/astro.config.mjs @@ -7,7 +7,4 @@ export default defineConfig({ redirects: { '/redirect': '/' }, - experimental: { - redirects: true - } }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cca772f05eeb..5781ec5b9ce6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -485,8 +485,8 @@ importers: packages/astro: dependencies: '@astrojs/compiler': - specifier: ^1.5.3 - version: 1.5.3 + specifier: ^1.6.0 + version: 1.6.0 '@astrojs/internal-helpers': specifier: ^0.1.1 version: link:../internal-helpers @@ -523,6 +523,9 @@ importers: '@types/babel__core': specifier: ^7.20.1 version: 7.20.1 + '@types/dom-view-transitions': + specifier: ^1.0.1 + version: 1.0.1 '@types/yargs-parser': specifier: ^21.0.0 version: 21.0.0 @@ -592,6 +595,9 @@ importers: mime: specifier: ^3.0.0 version: 3.0.0 + network-information-types: + specifier: ^0.1.1 + version: 0.1.1(typescript@5.0.2) ora: specifier: ^6.3.1 version: 6.3.1 @@ -1478,6 +1484,12 @@ importers: specifier: ^18.1.0 version: 18.2.0(react@18.2.0) + packages/astro/e2e/fixtures/view-transitions: + dependencies: + astro: + specifier: workspace:* + version: link:../../.. + packages/astro/e2e/fixtures/vue-component: dependencies: '@astrojs/mdx': @@ -5523,14 +5535,14 @@ packages: sisteransi: 1.0.5 dev: false - /@astrojs/compiler@1.5.3: - resolution: {integrity: sha512-/HSFkJ+Yv+WUWSq0QVsIlhBKam5VUpGV+s8MvPguC/krHmw4Ww9TIgmfJSvV8/BN0sHJB7pCgf7yInae1zb+TQ==} + /@astrojs/compiler@1.6.0: + resolution: {integrity: sha512-vxuzp09jAW/ZQ8C4Itf6/OsF76TNjBQC06FNpcayKOzxYkCGHTLh7+0lF4ywmG/fDgSc+f1x7kKxxEKl4nqXvQ==} /@astrojs/language-server@1.0.0: resolution: {integrity: sha512-oEw7AwJmzjgy6HC9f5IdrphZ1GVgfV/+7xQuyf52cpTiRWd/tJISK3MsKP0cDkVlfodmNABNFnAaAWuLZEiiiA==} hasBin: true dependencies: - '@astrojs/compiler': 1.5.3 + '@astrojs/compiler': 1.6.0 '@jridgewell/trace-mapping': 0.3.18 '@vscode/emmet-helper': 2.8.8 events: 3.3.0 @@ -8580,6 +8592,10 @@ packages: resolution: {integrity: sha512-OyiZ3jEKu7RtGO1yp9oOdK0cTwZ/10oE9PDJ6fyN3r9T5wkyOcvr6awdugjYdqF6KVO5eUvt7jx7rk2Eylufow==} dev: true + /@types/dom-view-transitions@1.0.1: + resolution: {integrity: sha512-A9S1ijj/4MX06I1W/6on8lhaYyq1Ir7gaOvfllW1o4RzVWW88HAeqX0pUx9VgOLnNpdiGeUW2CTkg18p5LWIrA==} + dev: false + /@types/estree-jsx@1.0.0: resolution: {integrity: sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ==} dependencies: @@ -14232,6 +14248,14 @@ packages: engines: {node: '>= 0.4.0'} dev: true + /network-information-types@0.1.1(typescript@5.0.2): + resolution: {integrity: sha512-mLXNafJYOkiJB6IlF727YWssTRpXitR+tKSLyA5VAdBi3SOvLf5gtizHgxf241YHPWocnAO/fAhVrB/68tPHDw==} + peerDependencies: + typescript: '>= 3.0.0' + dependencies: + typescript: 5.0.2 + dev: false + /nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true @@ -15298,7 +15322,7 @@ packages: resolution: {integrity: sha512-dPzop0gKZyVGpTDQmfy+e7FKXC9JT3mlpfYA2diOVz+Ui+QR1U4G/s+OesKl2Hib2JJOtAYJs/l+ovgT0ljlFA==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} dependencies: - '@astrojs/compiler': 1.5.3 + '@astrojs/compiler': 1.6.0 prettier: 2.8.8 sass-formatter: 0.7.6 dev: true @@ -15307,7 +15331,7 @@ packages: resolution: {integrity: sha512-lJ/mG/Lz/ccSwNtwqpFS126mtMVzFVyYv0ddTF9wqwrEG4seECjKDAyw/oGv915rAcJi8jr89990nqfpmG+qdg==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} dependencies: - '@astrojs/compiler': 1.5.3 + '@astrojs/compiler': 1.6.0 prettier: 2.8.8 sass-formatter: 0.7.6 synckit: 0.8.5