├── .gitignore ├── README.md ├── app ├── blog │ ├── [slug] │ │ ├── page-client.tsx │ │ └── page.tsx │ └── page.tsx ├── card │ ├── [slug] │ │ ├── page-client.tsx │ │ └── page.tsx │ ├── overview │ │ └── page.tsx │ ├── page.tsx │ └── styles.module.css ├── globals.css ├── icon.svg ├── layout.tsx ├── page.tsx └── utils │ ├── constants.ts │ └── cx.ts ├── components.json ├── components ├── transition │ └── slide-transition.tsx └── ui │ ├── avatar.tsx │ ├── button.tsx │ ├── card.tsx │ └── dynamic-background.tsx ├── lib └── utils.ts ├── next.config.ts ├── package.json ├── pnpm-lock.yaml ├── postcss.config.mjs ├── public ├── avatars │ ├── feedthejim.jpg │ ├── huozhi.jpg │ ├── leerob.jpg │ ├── sebmarkbage.jpg │ └── ztanner.jpg ├── cards │ ├── barcelona.png │ ├── florence.png │ ├── santamonica.png │ └── xian.png └── post │ └── composable-caching-with-nextjs.png ├── tailwind.config.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org) project that demonstrates the React experimental ViewTransition component. 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | pnpm dev 9 | ``` 10 | 11 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 12 | 13 | 14 | ## Deploy on Vercel 15 | 16 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 17 | 18 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. 19 | -------------------------------------------------------------------------------- /app/blog/[slug]/page-client.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { unstable_ViewTransition as ViewTransition } from 'react' 4 | import Link from 'next/link' 5 | import { Avatar } from '@/components/ui/avatar' 6 | import { type Post } from '@/app/utils/constants' 7 | 8 | export default function BlogPost({ post }: { post: Post }) { 9 | const { slug } = post 10 | return ( 11 | 12 |
13 |
14 | 15 | ← Back to blog 16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | {/* Add a div to hack the transition from Link to h1 on safari, where it needs to be a inline-block */} 24 |
25 | 26 |

{post.title}

27 |
28 |
29 |
30 | 31 |
32 |

Posted by

33 | 34 |
35 | {post?.authors.map((author, i) => { 36 | return ( 37 |
38 | 39 | 40 | 41 | 42 | 43 |
44 | {author.name} 45 | {author.handle} 46 |
47 |
48 | ) 49 | })} 50 |
51 |
52 |
53 | 54 | 55 |
    56 | {post.features && 57 | post.features.map((feature) => ( 58 |
  • 59 | 60 | {feature.title} 61 | 62 | : {feature.description} 63 |
  • 64 | ))} 65 |
66 | 67 |
{post.content}
68 | 69 | <> 70 | {'image' in post && post.image ? ( 71 |
72 | {/* @ts-ignore */} 73 | 74 |
75 | ) : null} 76 | 77 |
78 |
79 |
80 |
81 | ) 82 | } 83 | -------------------------------------------------------------------------------- /app/blog/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import { POSTS } from '@/app/utils/constants' 2 | import { default as PageClient } from './page-client' 3 | 4 | export default async function Page( 5 | props: { params: Promise<{ slug: string }> } 6 | ) { 7 | const { slug } = await props.params 8 | const post = POSTS.find((item) => item.slug === slug)! 9 | 10 | return 11 | } 12 | 13 | 14 | 15 | export async function generateStaticParams() { 16 | return POSTS.map((post) => ({ 17 | params: { slug: post.slug }, 18 | })) 19 | } 20 | 21 | export const dynamic = 'force-static' 22 | -------------------------------------------------------------------------------- /app/blog/page.tsx: -------------------------------------------------------------------------------- 1 | import { unstable_ViewTransition as ViewTransition } from 'react' 2 | import Link from 'next/link' 3 | import { Avatar } from '@/components/ui/avatar' 4 | import { Card, CardContent, CardFooter } from '@/components/ui/card' 5 | import { Button } from '@/components/ui/button' 6 | import { cx } from '@/app/utils/cx' 7 | import { POSTS } from '../utils/constants' 8 | 9 | export default function Page() { 10 | return ( 11 | 12 |
13 | 14 | {``} 15 | 16 | {/* Go to home page */} 17 |
18 | 19 | ← Back 20 | 21 |
22 | 23 |

The latest Next.js news

24 | 25 |
26 | {POSTS.map((item, index) => ( 27 | 28 | 29 |
30 | {item.authors.map((author, i) => ( 31 | 32 | 33 | 34 | 35 | 36 | ))} 37 |
38 | 39 |
40 | 41 |

{item.date}

42 |
43 | 44 | {/* NOTE: inline-block is required for safari */} 45 | 46 |

{item.title}

47 | 48 |
49 | {null} 50 | 51 |

{item.description}

52 | 53 | {/* actually displayed features */} 54 |
55 | {item.features?.map((feature) => ( 56 |
57 | 58 | {feature.title} 59 | 60 |
61 | ))} 62 |
63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 |
72 | ))} 73 |
74 |
75 |
76 | ) 77 | } 78 | -------------------------------------------------------------------------------- /app/card/[slug]/page-client.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Image from 'next/image' 4 | import Link from 'next/link' 5 | import { unstable_ViewTransition as ViewTransition } from 'react' 6 | import { type Place } from '@/app/utils/constants' 7 | 8 | export default function Place({ place, places }: { place: Place; places: Place[] }) { 9 | return ( 10 |
11 |
12 |
13 | 14 | 18 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | {place.name} 40 |
41 |
42 | 43 | 44 |
45 |
46 | {place.name} 47 |
48 |
49 |
50 |
51 | 52 | 53 |
54 |

Spots

55 |
56 | {places.map((place) => ( 57 | 62 |
63 | 64 | {place.name} 72 | {/* name label */} 73 | 74 |
75 |
{place.name}
76 | 77 | ))} 78 |
79 |
80 |
81 |
82 |
83 | ) 84 | } 85 | -------------------------------------------------------------------------------- /app/card/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import { PLACES } from '@/app/utils/constants' 2 | 3 | import { default as PageClient } from './page-client' 4 | 5 | export default async function Page( 6 | props: { params: Promise<{ slug: string }> } 7 | ) { 8 | const params = await props.params 9 | const place = PLACES.find((p) => p.slug === params.slug)! 10 | 11 | return 12 | } 13 | 14 | export async function generateStaticParams() { 15 | return PLACES.map((place) => ({ 16 | params: { slug: place.slug }, 17 | })) 18 | } 19 | 20 | export const dynamic = 'force-static' 21 | -------------------------------------------------------------------------------- /app/card/overview/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Image from 'next/image' 4 | import Link from 'next/link' 5 | import { unstable_ViewTransition as ViewTransition } from 'react' 6 | import { PLACES } from '@/app/utils/constants' 7 | import { DynamicBackground } from '@/components/ui/dynamic-background' 8 | 9 | function LeftSideBar() { 10 | return ( 11 |
12 |
13 | 14 |
15 |
16 | {/* sticker icon */} 17 | 18 | 19 | 20 | 21 | 22 |
23 |
24 |
25 |
26 | ) 27 | } 28 | 29 | export default function Page() { 30 | return ( 31 |
32 | {/* Left Section */} 33 | 34 | 35 | 36 | 37 | {/* Right Section */} 38 | 39 |
40 |

Spots

41 |
42 | {PLACES.map((place) => ( 43 | 48 | 49 |
50 | {place.name} 58 |
59 |
60 |
61 |

{place.name}

62 | {place.description} 63 |
64 | 65 | ))} 66 |
67 |
68 |
69 |
70 | ) 71 | } 72 | -------------------------------------------------------------------------------- /app/card/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Image from 'next/image' 4 | import Link from 'next/link' 5 | import { unstable_ViewTransition as ViewTransition } from 'react' 6 | import { PLACES } from '../utils/constants' 7 | import { DynamicBackground } from '@/components/ui/dynamic-background' 8 | 9 | function LeftSideMenu() { 10 | return ( 11 |
12 |
13 | 14 | 15 |
16 | 17 | {``} 18 | 19 |
20 | 21 | ← Back 22 | 23 |
24 |
25 | 26 | 27 | {/* sticker icon */} 28 |
29 | 30 | 31 | 32 | 33 | 34 | Las Ciudades 35 |
36 | 37 |
38 |

39 |
40 | Explore The cities. 41 |
42 |

43 |
44 |
45 |
46 | ) 47 | } 48 | 49 | export default function Page() { 50 | return ( 51 | // make this locate on top of the page when it's on mobile 52 |
53 | {/* Left Section */} 54 | 55 | 56 | 57 | 58 | {/* Right Section */} 59 | 60 |
61 |

Spots

62 |
63 | {PLACES.map((place) => ( 64 | 69 |
70 | 71 | {place.name} 79 | 80 | {/* name label */} 81 | 82 |
83 | {place.name} 84 |
85 |
86 |
87 | 88 | ))} 89 |
90 |
91 |
92 |
93 | ) 94 | } 95 | -------------------------------------------------------------------------------- /app/card/styles.module.css: -------------------------------------------------------------------------------- 1 | @keyframes enter-slide-left { 2 | 0% { 3 | /* opacity: 0; */ 4 | transform: translate(60px, 0); 5 | } 6 | 100% { 7 | /* opacity: 1; */ 8 | transform: translate(0, 0); 9 | } 10 | } 11 | 12 | @keyframes exit-slide-right { 13 | 0% { 14 | /* opacity: 1; */ 15 | transform: translate(0, 0); 16 | } 17 | 100% { 18 | /* opacity: 0; */ 19 | transform: translate(-60px, 0); 20 | 21 | } 22 | } 23 | 24 | ::view-transition-new(.enter-slide-left) { 25 | animation: enter-slide-left ease-in 300ms; 26 | animation-delay: 300ms; 27 | } 28 | ::view-transition-old(.exit-slide-right) { 29 | animation: exit-slide-right ease-out 300ms; 30 | animation-delay: 300ms; 31 | } 32 | 33 | 34 | @keyframes spin-90-forward { 35 | 0% { 36 | transform: rotate(0deg); 37 | } 38 | 100% { 39 | transform: rotate(90deg); 40 | } 41 | } 42 | 43 | @keyframes spin-90-backward { 44 | 0% { 45 | transform: rotate(0deg); 46 | } 47 | 100% { 48 | transform: rotate(-90deg); 49 | } 50 | } 51 | 52 | ::view-transition-new(.spin-90-forward) { 53 | animation: spin-90-forward ease-in 300ms; 54 | } 55 | ::view-transition-old(.spin-90-backward) { 56 | animation: spin-90-backward ease-out 300ms; 57 | } 58 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | 3 | @theme { 4 | --font-sans: var(--font-geist-sans); 5 | --font-mono: var(--font-geist-mono); 6 | } 7 | 8 | @layer utilities { 9 | .text-balance { 10 | text-wrap: balance; 11 | } 12 | } 13 | 14 | 15 | 16 | @layer base { 17 | :root { 18 | --background: 0 0% 100%; 19 | --foreground: 0 0% 3.9%; 20 | --card: 0 0% 100%; 21 | --card-foreground: 0 0% 3.9%; 22 | --popover: 0 0% 100%; 23 | --popover-foreground: 0 0% 3.9%; 24 | --primary: 0 0% 9%; 25 | --primary-foreground: 0 0% 98%; 26 | --secondary: 0 0% 96.1%; 27 | --secondary-foreground: 0 0% 9%; 28 | --muted: 0 0% 96.1%; 29 | --muted-foreground: 0 0% 45.1%; 30 | --accent: 0 0% 96.1%; 31 | --accent-foreground: 0 0% 9%; 32 | --destructive: 0 84.2% 60.2%; 33 | --destructive-foreground: 0 0% 98%; 34 | --border: 0 0% 89.8%; 35 | --input: 0 0% 89.8%; 36 | --ring: 0 0% 3.9%; 37 | --chart-1: 12 76% 61%; 38 | --chart-2: 173 58% 39%; 39 | --chart-3: 197 37% 24%; 40 | --chart-4: 43 74% 66%; 41 | --chart-5: 27 87% 67%; 42 | --radius: 0.5rem; 43 | } 44 | .dark { 45 | --background: 0 0% 3.9%; 46 | --foreground: 0 0% 98%; 47 | --card: 0 0% 3.9%; 48 | --card-foreground: 0 0% 98%; 49 | --popover: 0 0% 3.9%; 50 | --popover-foreground: 0 0% 98%; 51 | --primary: 0 0% 98%; 52 | --primary-foreground: 0 0% 9%; 53 | --secondary: 0 0% 14.9%; 54 | --secondary-foreground: 0 0% 98%; 55 | --muted: 0 0% 14.9%; 56 | --muted-foreground: 0 0% 63.9%; 57 | --accent: 0 0% 14.9%; 58 | --accent-foreground: 0 0% 98%; 59 | --destructive: 0 62.8% 30.6%; 60 | --destructive-foreground: 0 0% 98%; 61 | --border: 0 0% 14.9%; 62 | --input: 0 0% 14.9%; 63 | --ring: 0 0% 83.1%; 64 | --chart-1: 220 70% 50%; 65 | --chart-2: 160 60% 45%; 66 | --chart-3: 30 80% 55%; 67 | --chart-4: 280 65% 60%; 68 | --chart-5: 340 75% 55%; 69 | } 70 | } 71 | 72 | [data-support-yes], 73 | [data-support-no] { 74 | display: none; 75 | } 76 | 77 | 78 | @supports (view-transition-name: test) { 79 | [data-support] [data-support-yes] { 80 | display: inline; 81 | } 82 | [data-support] [data-support-no] { 83 | display: none; 84 | } 85 | } 86 | 87 | @supports not (view-transition-name: test) { 88 | [data-support] [data-support-yes] { 89 | display: none; 90 | } 91 | [data-support] [data-support-no] { 92 | display: inline; 93 | } 94 | } 95 | 96 | /* Safari */ 97 | @supports (-webkit-hyphens: none) and (not (-moz-appearance: none)) { 98 | [data-support] [data-support-yes] { 99 | display: none; 100 | } 101 | [data-support] [data-support-no] { 102 | display: inline; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /app/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from 'next' 2 | import './globals.css' 3 | 4 | export const metadata: Metadata = { 5 | title: 'Next.js View Transition', 6 | description: 'Next.js View Transition Examples', 7 | } 8 | 9 | export default function RootLayout({ 10 | children, 11 | }: Readonly<{ 12 | children: React.ReactNode 13 | }>) { 14 | return ( 15 | 16 | {children} 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import { unstable_ViewTransition as ViewTransition } from 'react' 3 | 4 | export default function Page() { 5 | return ( 6 |
7 |

{'View Transition Next.js Examples'}

8 | 9 |

10 | 11 | {`Use React `} 12 | {`Experimental `} 13 | 14 | 15 | {``} 16 | 17 | 18 | {` API in Next.js.`} 19 | 20 |

21 | 22 | {/* supports info */} 23 |
24 |

25 | {'🔴 might not work well on your browser'} 26 |

27 |

28 | 🟢 Your browser supports View Transitions. 29 |

30 |
31 | 32 |
    33 |
  • 34 |

    35 | {`Floating Elements Transition`} 36 |

    37 |
  • 38 | 39 |
  • 40 |

    41 | {`Transform Card Transition`} 42 |

    43 |
  • 44 |
45 | 46 | 47 | Source code ↗ 48 | 49 |
50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /app/utils/constants.ts: -------------------------------------------------------------------------------- 1 | interface Author { 2 | name: string 3 | handle: string 4 | avatar: string 5 | } 6 | 7 | const AUTHORS: Record = { 8 | 'sebmarkbage': { name: 'Sebastian Silbermann', handle: 'sebmarkbage', avatar: '/avatars/sebmarkbage.jpg' }, 9 | 'huozhi': { name: 'Jiachi Liu', handle: 'huozhi', avatar: '/avatars/huozhi.jpg' }, 10 | 'ztanner': { name: 'Zack Tanner', handle: 'ztanner', avatar: '/avatars/ztanner.jpg' }, 11 | 'leerob': { name: 'Lee Robinson', handle: 'leerob', avatar: '/avatars/leerob.jpg' }, 12 | 'feedthejim': { name: 'Jimmy Lai', handle: 'feedthejim', avatar: '/avatars/feedthejim.jpg' }, 13 | } 14 | 15 | export const POSTS = [ 16 | { 17 | date: 'February 26th, 2025', 18 | title: 'Next.js 15.2', 19 | slug: 'nextjs-15-2', 20 | description: 'Next.js 15.2 includes updates for debugging errors, metadata, Turbopack, and more:', 21 | features: [ 22 | { 23 | title: 'Redesigned error UI and improved stack traces', 24 | description: 'A redesigned debugging experience', 25 | }, 26 | { 27 | title: 'Streaming metadata', 28 | description: 'Async metadata will no longer block page rendering or client-side page transitions', 29 | }, 30 | { 31 | title: 'Turbopack performance improvements', 32 | description: 'Faster compile times and reduced memory usage', 33 | }, 34 | { 35 | title: 'React View Transitions (experimental)', 36 | description: "Experimental support for React's new View Transitions API", 37 | }, 38 | { 39 | title: 'Node.js Middleware (experimental)', 40 | description: 'Experimental support for using the Node.js runtime in Middleware', 41 | }, 42 | ], 43 | authors: ['sebmarkbage', 'huozhi', 'ztanner'].map((author) => AUTHORS[author]), 44 | content: `We've added a feature flag to enable the new experimental View Transitions API in React. This new API allows you to animate between different views and components in your application. 45 | 46 | We've overhauled the UI and presentation of error messages in Next.js, making them easier to understand. The new design highlights the core details of the error—such as the message, the relevant code frame, and the call stack—while reducing noise from code in libraries or dependencies. This means you can quickly get to the root of what went wrong and start fixing it faster. 47 | 48 | Leveraging the newly introduced owner stacks feature in React, we're now able to provide higher fidelity into where your errors are coming from. Next.js will now be able to surface the subcomponent responsible for throwing the error, skipping over intermediary elements that weren't responsible for creating the element that caused the error. 49 | 50 | We're also making it easier to customize your indicator preferences without needing to add additional configuration. 51 | `, 52 | image: null, 53 | }, 54 | { 55 | date: 'January 3rd, 2025', 56 | title: 'Composable Caching with Next.js', 57 | slug: 'composable-caching-with-nextjs', 58 | description: 59 | "We're working on a simple and powerful caching model for Next.js. In a previous post, we talked about our journey with caching and how we've arrived at the 'use cache'", 60 | 61 | authors: ['leerob'].map((author) => AUTHORS[author]), 62 | content: `We’re working on a simple and powerful caching model for Next.js. In a previous post, we talked about our journey with caching and how we’ve arrived at the 'use cache' directive. 63 | 64 | This post will discuss the API design and benefits of 'use cache'. 65 | 66 | Behind the scenes, Next.js transforms this code into a server function due to the 'use cache' directive. During compilation, the “dependencies” of this cache entry are found and used as part of the cache key. 67 | 68 | For example, id becomes part of the cache key. If we call getUser(1) multiple times, we return the memoized output from the cached server function. Changing this value will create a new entry in the cache. 69 | `, 70 | image: '/post/composable-caching-with-nextjs.png', 71 | }, 72 | { 73 | date: 'December 10th, 2024', 74 | title: 'Next.js 14.1', 75 | slug: 'next-14-1', 76 | description: 77 | 'Next.js 14.1 includes developer experience improvements including:', 78 | authors: ['huozhi', 'feedthejim'].map((author) => AUTHORS[author]), 79 | features: [ 80 | { 81 | title: 'Improved Self-Hosting', 82 | description: 'New documentation and custom cache handler', 83 | }, 84 | { 85 | title: 'Turbopack Improvements', 86 | description: '5,600 tests passing for next dev --turbo', 87 | }, 88 | { 89 | title: 'DX Improvements', 90 | description: 'Improved error messages, pushState and replaceState support', 91 | }, 92 | { 93 | title: 'Parallel & Intercepted Routes', 94 | description: '20 bug fixes based on your feedback', 95 | }, 96 | { 97 | title: 'next/image Improvements', 98 | description: ', art direction, and dark mode support', 99 | }, 100 | ], 101 | content: `Improved Self-Hosting 102 | 103 | We've heard your feedback for improved clarity on how to self-host Next.js with a Node.js server, Docker container, or static export. We've overhauled our self-hosting documentation on: 104 | 105 | - Runtime environment variables 106 | - Custom cache configuration for ISR 107 | - Custom image optimization 108 | - Middleware 109 | 110 | `, 111 | image: null, 112 | }, 113 | ] 114 | 115 | export const PLACES = [ 116 | { 117 | id: 1, 118 | name: 'Florence', 119 | image: '/cards/florence.png', 120 | slug: 'florence', 121 | // generate human description of the place 122 | description: `A city in central Italy and the capital city of the Tuscany region. It is the most populous city in Tuscany, with 383,084 inhabitants in 2013, and over 1,520,000 in its metropolitan area.`, 123 | }, 124 | { 125 | id: 2, 126 | name: `Xi'an`, 127 | image: '/cards/xian.png', 128 | slug: 'xian', 129 | description: 'An ancient city in China with 2000 years history, amazing food, located in the central part of the Shaanxi Province.', 130 | }, 131 | { 132 | id: 3, 133 | name: 'Barcelona', 134 | image: '/cards/barcelona.png', 135 | slug: 'barcelona', 136 | description: 'A city on the coast of northeastern Spain. It is the capital and largest city of the autonomous community of Catalonia, as well as the second most populous municipality of Spain.', 137 | }, 138 | { 139 | id: 4, 140 | name: 'Santa Monica', 141 | image: '/cards/santamonica.png', 142 | slug: 'santamonica', 143 | description: 'A beachfront city in western Los Angeles County, California, United States. Situated on Santa Monica Bay, it is bordered on five sides by different neighborhoods of the city of Los Angeles.', 144 | }, 145 | ] 146 | 147 | export type Post = typeof POSTS[number] 148 | export type Place = typeof PLACES[number] 149 | -------------------------------------------------------------------------------- /app/utils/cx.ts: -------------------------------------------------------------------------------- 1 | export const cx = (...classes: (string | undefined | null | false)[]): string => { 2 | return classes.filter(Boolean).join(' ') 3 | } 4 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /components/transition/slide-transition.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { unstable_ViewTransition as ViewTransition } from 'react' 4 | import { cx } from '@/app/utils/cx' 5 | 6 | export function SlideTransition({ 7 | name, 8 | children, 9 | direction = 'horizontal', 10 | distance = 100, 11 | duration = 200, 12 | }: { 13 | name: string 14 | children: React.ReactNode 15 | direction?: 'horizontal' | 'vertical' 16 | distance?: number 17 | duration?: number 18 | }) { 19 | const isHorizontal = direction === 'horizontal' 20 | const startName = isHorizontal ? 'left' : 'up' 21 | const endName = isHorizontal ? 'right' : 'down' 22 | const startPosition = isHorizontal ? `-${distance}px 0` : `0 ${distance}px` 23 | const endPosition = isHorizontal ? `${distance}px 0` : `0 100%` 24 | 25 | return ( 26 | <> 27 | 59 | 60 | {children} 61 | 62 | 63 | ) 64 | } 65 | -------------------------------------------------------------------------------- /components/ui/avatar.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as AvatarPrimitive from "@radix-ui/react-avatar" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | const Avatar = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | )) 21 | Avatar.displayName = AvatarPrimitive.Root.displayName 22 | 23 | const AvatarImage = React.forwardRef< 24 | React.ElementRef, 25 | React.ComponentPropsWithoutRef 26 | >(({ className, ...props }, ref) => ( 27 | 32 | )) 33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName 34 | 35 | const AvatarFallback = React.forwardRef< 36 | React.ElementRef, 37 | React.ComponentPropsWithoutRef 38 | >(({ className, ...props }, ref) => ( 39 | 47 | )) 48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName 49 | 50 | export { Avatar, AvatarImage, AvatarFallback } 51 | -------------------------------------------------------------------------------- /components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | } 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button" 45 | return ( 46 | 51 | ) 52 | } 53 | ) 54 | Button.displayName = "Button" 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
17 | )) 18 | Card.displayName = "Card" 19 | 20 | const CardHeader = React.forwardRef< 21 | HTMLDivElement, 22 | React.HTMLAttributes 23 | >(({ className, ...props }, ref) => ( 24 |
29 | )) 30 | CardHeader.displayName = "CardHeader" 31 | 32 | const CardTitle = React.forwardRef< 33 | HTMLDivElement, 34 | React.HTMLAttributes 35 | >(({ className, ...props }, ref) => ( 36 |
44 | )) 45 | CardTitle.displayName = "CardTitle" 46 | 47 | const CardDescription = React.forwardRef< 48 | HTMLDivElement, 49 | React.HTMLAttributes 50 | >(({ className, ...props }, ref) => ( 51 |
56 | )) 57 | CardDescription.displayName = "CardDescription" 58 | 59 | const CardContent = React.forwardRef< 60 | HTMLDivElement, 61 | React.HTMLAttributes 62 | >(({ className, ...props }, ref) => ( 63 |
64 | )) 65 | CardContent.displayName = "CardContent" 66 | 67 | const CardFooter = React.forwardRef< 68 | HTMLDivElement, 69 | React.HTMLAttributes 70 | >(({ className, ...props }, ref) => ( 71 |
76 | )) 77 | CardFooter.displayName = "CardFooter" 78 | 79 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } 80 | -------------------------------------------------------------------------------- /components/ui/dynamic-background.tsx: -------------------------------------------------------------------------------- 1 | import { cx } from '@/app/utils/cx' 2 | 3 | export function DynamicBackground({ className }: { className?: string }) { 4 | return ( 5 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from 'next' 2 | 3 | const nextConfig: NextConfig = { 4 | experimental: { 5 | viewTransition: true, 6 | }, 7 | } 8 | 9 | export default nextConfig 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-view-transition-example", 3 | "private": true, 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start", 8 | "lint": "next lint" 9 | }, 10 | "dependencies": { 11 | "@radix-ui/react-avatar": "^1.1.3", 12 | "@radix-ui/react-slot": "^1.1.2", 13 | "class-variance-authority": "^0.7.1", 14 | "clsx": "^2.1.1", 15 | "lucide-react": "^0.477.0", 16 | "next": "15.3.1-canary.15", 17 | "react": "^19.0.0", 18 | "react-dom": "^19.0.0", 19 | "tailwind-merge": "^3.0.2", 20 | "tailwindcss-animate": "^1.0.7" 21 | }, 22 | "devDependencies": { 23 | "@tailwindcss/postcss": "^4.0.9", 24 | "@types/node": "^22", 25 | "@types/react": "^19", 26 | "@types/react-dom": "^19", 27 | "tailwindcss": "^4.0.9", 28 | "typescript": "^5" 29 | }, 30 | "packageManager": "pnpm@9.15.4" 31 | } 32 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@radix-ui/react-avatar': 12 | specifier: ^1.1.3 13 | version: 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 14 | '@radix-ui/react-slot': 15 | specifier: ^1.1.2 16 | version: 1.1.2(@types/react@19.0.10)(react@19.0.0) 17 | class-variance-authority: 18 | specifier: ^0.7.1 19 | version: 0.7.1 20 | clsx: 21 | specifier: ^2.1.1 22 | version: 2.1.1 23 | lucide-react: 24 | specifier: ^0.477.0 25 | version: 0.477.0(react@19.0.0) 26 | next: 27 | specifier: 15.3.1-canary.15 28 | version: 15.3.1-canary.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 29 | react: 30 | specifier: ^19.0.0 31 | version: 19.0.0 32 | react-dom: 33 | specifier: ^19.0.0 34 | version: 19.0.0(react@19.0.0) 35 | tailwind-merge: 36 | specifier: ^3.0.2 37 | version: 3.0.2 38 | tailwindcss-animate: 39 | specifier: ^1.0.7 40 | version: 1.0.7(tailwindcss@4.0.9) 41 | devDependencies: 42 | '@tailwindcss/postcss': 43 | specifier: ^4.0.9 44 | version: 4.0.9 45 | '@types/node': 46 | specifier: ^22 47 | version: 22.13.8 48 | '@types/react': 49 | specifier: ^19 50 | version: 19.0.10 51 | '@types/react-dom': 52 | specifier: ^19 53 | version: 19.0.4(@types/react@19.0.10) 54 | tailwindcss: 55 | specifier: ^4.0.9 56 | version: 4.0.9 57 | typescript: 58 | specifier: ^5 59 | version: 5.8.2 60 | 61 | packages: 62 | 63 | '@alloc/quick-lru@5.2.0': 64 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 65 | engines: {node: '>=10'} 66 | 67 | '@emnapi/runtime@1.4.3': 68 | resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} 69 | 70 | '@img/sharp-darwin-arm64@0.34.1': 71 | resolution: {integrity: sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==} 72 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 73 | cpu: [arm64] 74 | os: [darwin] 75 | 76 | '@img/sharp-darwin-x64@0.34.1': 77 | resolution: {integrity: sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==} 78 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 79 | cpu: [x64] 80 | os: [darwin] 81 | 82 | '@img/sharp-libvips-darwin-arm64@1.1.0': 83 | resolution: {integrity: sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==} 84 | cpu: [arm64] 85 | os: [darwin] 86 | 87 | '@img/sharp-libvips-darwin-x64@1.1.0': 88 | resolution: {integrity: sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==} 89 | cpu: [x64] 90 | os: [darwin] 91 | 92 | '@img/sharp-libvips-linux-arm64@1.1.0': 93 | resolution: {integrity: sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==} 94 | cpu: [arm64] 95 | os: [linux] 96 | 97 | '@img/sharp-libvips-linux-arm@1.1.0': 98 | resolution: {integrity: sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==} 99 | cpu: [arm] 100 | os: [linux] 101 | 102 | '@img/sharp-libvips-linux-ppc64@1.1.0': 103 | resolution: {integrity: sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==} 104 | cpu: [ppc64] 105 | os: [linux] 106 | 107 | '@img/sharp-libvips-linux-s390x@1.1.0': 108 | resolution: {integrity: sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==} 109 | cpu: [s390x] 110 | os: [linux] 111 | 112 | '@img/sharp-libvips-linux-x64@1.1.0': 113 | resolution: {integrity: sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==} 114 | cpu: [x64] 115 | os: [linux] 116 | 117 | '@img/sharp-libvips-linuxmusl-arm64@1.1.0': 118 | resolution: {integrity: sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==} 119 | cpu: [arm64] 120 | os: [linux] 121 | 122 | '@img/sharp-libvips-linuxmusl-x64@1.1.0': 123 | resolution: {integrity: sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==} 124 | cpu: [x64] 125 | os: [linux] 126 | 127 | '@img/sharp-linux-arm64@0.34.1': 128 | resolution: {integrity: sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==} 129 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 130 | cpu: [arm64] 131 | os: [linux] 132 | 133 | '@img/sharp-linux-arm@0.34.1': 134 | resolution: {integrity: sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==} 135 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 136 | cpu: [arm] 137 | os: [linux] 138 | 139 | '@img/sharp-linux-s390x@0.34.1': 140 | resolution: {integrity: sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==} 141 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 142 | cpu: [s390x] 143 | os: [linux] 144 | 145 | '@img/sharp-linux-x64@0.34.1': 146 | resolution: {integrity: sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==} 147 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 148 | cpu: [x64] 149 | os: [linux] 150 | 151 | '@img/sharp-linuxmusl-arm64@0.34.1': 152 | resolution: {integrity: sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==} 153 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 154 | cpu: [arm64] 155 | os: [linux] 156 | 157 | '@img/sharp-linuxmusl-x64@0.34.1': 158 | resolution: {integrity: sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==} 159 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 160 | cpu: [x64] 161 | os: [linux] 162 | 163 | '@img/sharp-wasm32@0.34.1': 164 | resolution: {integrity: sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==} 165 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 166 | cpu: [wasm32] 167 | 168 | '@img/sharp-win32-ia32@0.34.1': 169 | resolution: {integrity: sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==} 170 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 171 | cpu: [ia32] 172 | os: [win32] 173 | 174 | '@img/sharp-win32-x64@0.34.1': 175 | resolution: {integrity: sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==} 176 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 177 | cpu: [x64] 178 | os: [win32] 179 | 180 | '@next/env@15.3.1-canary.15': 181 | resolution: {integrity: sha512-68oU7HJBCSeEp9ESMvrCSTKJN45s9ck7ZC/32x/HW9RfT8zr2osBiuOp4z2GYA+h+nUPu2oElfMpq7AamYR4Dw==} 182 | 183 | '@next/swc-darwin-arm64@15.3.1-canary.15': 184 | resolution: {integrity: sha512-OQCjX6Vte2k5OAPrWhPRtox2XnY1PwTvdr+bFVVrru6MSRbAqJW09u4GYK65at7hhILiAAMyhCk6yTq46beUaw==} 185 | engines: {node: '>= 10'} 186 | cpu: [arm64] 187 | os: [darwin] 188 | 189 | '@next/swc-darwin-x64@15.3.1-canary.15': 190 | resolution: {integrity: sha512-KXP4QtAQKMJJ9yD9ALgvfdhZlOvSrHjh86dBaCn4pdnBQspyuv8bdvVFVQ72VBIKI/hi1I7Oy1tgNNz3YX1vxA==} 191 | engines: {node: '>= 10'} 192 | cpu: [x64] 193 | os: [darwin] 194 | 195 | '@next/swc-linux-arm64-gnu@15.3.1-canary.15': 196 | resolution: {integrity: sha512-BuM+AzhU7ujlZguFArh55L3lseAyu6IpS6aZNAcM0mx+ug9hl3/K5DYEofr5hl36j6g4S04N6JMC2u9ThHlTbg==} 197 | engines: {node: '>= 10'} 198 | cpu: [arm64] 199 | os: [linux] 200 | 201 | '@next/swc-linux-arm64-musl@15.3.1-canary.15': 202 | resolution: {integrity: sha512-PqVdd1NhheFnVheEfAFdZGx2glpsoKG4Vjd2pl2MkCf/MEqUYFdzBtAaOcBlir1HN7eI2y7FixUbpjFQu2m7gg==} 203 | engines: {node: '>= 10'} 204 | cpu: [arm64] 205 | os: [linux] 206 | 207 | '@next/swc-linux-x64-gnu@15.3.1-canary.15': 208 | resolution: {integrity: sha512-JbtEqPbZoeWtpsDNwJxps+P24RKPQpE7eK8hRK7kGf9x2tAVVQZdOVVGjnzYC8WIibGi0FgXT7Q3UqtI5gR7JA==} 209 | engines: {node: '>= 10'} 210 | cpu: [x64] 211 | os: [linux] 212 | 213 | '@next/swc-linux-x64-musl@15.3.1-canary.15': 214 | resolution: {integrity: sha512-b8k1IIKSUYCsZFQFEr3iLskRDBATCc5lcpDRje2Z7PYV1Oe7vOzmf5gmtknn6YZdyFV1qNRhf9hHl6l4NPgyaw==} 215 | engines: {node: '>= 10'} 216 | cpu: [x64] 217 | os: [linux] 218 | 219 | '@next/swc-win32-arm64-msvc@15.3.1-canary.15': 220 | resolution: {integrity: sha512-I5SL0FCHiEfcewsTpxMGZoIu1sE5BLgUWiJbtqdkByfnAaP9XVIzaeBvW1IRBmNFjAcJmqwDTZtcKlsOTVHh+Q==} 221 | engines: {node: '>= 10'} 222 | cpu: [arm64] 223 | os: [win32] 224 | 225 | '@next/swc-win32-x64-msvc@15.3.1-canary.15': 226 | resolution: {integrity: sha512-2HkLFhKDJI3Y6LYMUHUgNmsKDpssVlfWQTxXEBoYOmaoX1A5R3OjZKnnKjjiRnppKC0rrP97dTgMnzN+e1tQew==} 227 | engines: {node: '>= 10'} 228 | cpu: [x64] 229 | os: [win32] 230 | 231 | '@radix-ui/react-avatar@1.1.3': 232 | resolution: {integrity: sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==} 233 | peerDependencies: 234 | '@types/react': '*' 235 | '@types/react-dom': '*' 236 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 237 | react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 238 | peerDependenciesMeta: 239 | '@types/react': 240 | optional: true 241 | '@types/react-dom': 242 | optional: true 243 | 244 | '@radix-ui/react-compose-refs@1.1.1': 245 | resolution: {integrity: sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==} 246 | peerDependencies: 247 | '@types/react': '*' 248 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 249 | peerDependenciesMeta: 250 | '@types/react': 251 | optional: true 252 | 253 | '@radix-ui/react-context@1.1.1': 254 | resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} 255 | peerDependencies: 256 | '@types/react': '*' 257 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 258 | peerDependenciesMeta: 259 | '@types/react': 260 | optional: true 261 | 262 | '@radix-ui/react-primitive@2.0.2': 263 | resolution: {integrity: sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==} 264 | peerDependencies: 265 | '@types/react': '*' 266 | '@types/react-dom': '*' 267 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 268 | react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 269 | peerDependenciesMeta: 270 | '@types/react': 271 | optional: true 272 | '@types/react-dom': 273 | optional: true 274 | 275 | '@radix-ui/react-slot@1.1.2': 276 | resolution: {integrity: sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==} 277 | peerDependencies: 278 | '@types/react': '*' 279 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 280 | peerDependenciesMeta: 281 | '@types/react': 282 | optional: true 283 | 284 | '@radix-ui/react-use-callback-ref@1.1.0': 285 | resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} 286 | peerDependencies: 287 | '@types/react': '*' 288 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 289 | peerDependenciesMeta: 290 | '@types/react': 291 | optional: true 292 | 293 | '@radix-ui/react-use-layout-effect@1.1.0': 294 | resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} 295 | peerDependencies: 296 | '@types/react': '*' 297 | react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc 298 | peerDependenciesMeta: 299 | '@types/react': 300 | optional: true 301 | 302 | '@swc/counter@0.1.3': 303 | resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} 304 | 305 | '@swc/helpers@0.5.15': 306 | resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} 307 | 308 | '@tailwindcss/node@4.0.9': 309 | resolution: {integrity: sha512-tOJvdI7XfJbARYhxX+0RArAhmuDcczTC46DGCEziqxzzbIaPnfYaIyRT31n4u8lROrsO7Q6u/K9bmQHL2uL1bQ==} 310 | 311 | '@tailwindcss/oxide-android-arm64@4.0.9': 312 | resolution: {integrity: sha512-YBgy6+2flE/8dbtrdotVInhMVIxnHJPbAwa7U1gX4l2ThUIaPUp18LjB9wEH8wAGMBZUb//SzLtdXXNBHPUl6Q==} 313 | engines: {node: '>= 10'} 314 | cpu: [arm64] 315 | os: [android] 316 | 317 | '@tailwindcss/oxide-darwin-arm64@4.0.9': 318 | resolution: {integrity: sha512-pWdl4J2dIHXALgy2jVkwKBmtEb73kqIfMpYmcgESr7oPQ+lbcQ4+tlPeVXaSAmang+vglAfFpXQCOvs/aGSqlw==} 319 | engines: {node: '>= 10'} 320 | cpu: [arm64] 321 | os: [darwin] 322 | 323 | '@tailwindcss/oxide-darwin-x64@4.0.9': 324 | resolution: {integrity: sha512-4Dq3lKp0/C7vrRSkNPtBGVebEyWt9QPPlQctxJ0H3MDyiQYvzVYf8jKow7h5QkWNe8hbatEqljMj/Y0M+ERYJg==} 325 | engines: {node: '>= 10'} 326 | cpu: [x64] 327 | os: [darwin] 328 | 329 | '@tailwindcss/oxide-freebsd-x64@4.0.9': 330 | resolution: {integrity: sha512-k7U1RwRODta8x0uealtVt3RoWAWqA+D5FAOsvVGpYoI6ObgmnzqWW6pnVwz70tL8UZ/QXjeMyiICXyjzB6OGtQ==} 331 | engines: {node: '>= 10'} 332 | cpu: [x64] 333 | os: [freebsd] 334 | 335 | '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.9': 336 | resolution: {integrity: sha512-NDDjVweHz2zo4j+oS8y3KwKL5wGCZoXGA9ruJM982uVJLdsF8/1AeKvUwKRlMBpxHt1EdWJSAh8a0Mfhl28GlQ==} 337 | engines: {node: '>= 10'} 338 | cpu: [arm] 339 | os: [linux] 340 | 341 | '@tailwindcss/oxide-linux-arm64-gnu@4.0.9': 342 | resolution: {integrity: sha512-jk90UZ0jzJl3Dy1BhuFfRZ2KP9wVKMXPjmCtY4U6fF2LvrjP5gWFJj5VHzfzHonJexjrGe1lMzgtjriuZkxagg==} 343 | engines: {node: '>= 10'} 344 | cpu: [arm64] 345 | os: [linux] 346 | 347 | '@tailwindcss/oxide-linux-arm64-musl@4.0.9': 348 | resolution: {integrity: sha512-3eMjyTC6HBxh9nRgOHzrc96PYh1/jWOwHZ3Kk0JN0Kl25BJ80Lj9HEvvwVDNTgPg154LdICwuFLuhfgH9DULmg==} 349 | engines: {node: '>= 10'} 350 | cpu: [arm64] 351 | os: [linux] 352 | 353 | '@tailwindcss/oxide-linux-x64-gnu@4.0.9': 354 | resolution: {integrity: sha512-v0D8WqI/c3WpWH1kq/HP0J899ATLdGZmENa2/emmNjubT0sWtEke9W9+wXeEoACuGAhF9i3PO5MeyditpDCiWQ==} 355 | engines: {node: '>= 10'} 356 | cpu: [x64] 357 | os: [linux] 358 | 359 | '@tailwindcss/oxide-linux-x64-musl@4.0.9': 360 | resolution: {integrity: sha512-Kvp0TCkfeXyeehqLJr7otsc4hd/BUPfcIGrQiwsTVCfaMfjQZCG7DjI+9/QqPZha8YapLA9UoIcUILRYO7NE1Q==} 361 | engines: {node: '>= 10'} 362 | cpu: [x64] 363 | os: [linux] 364 | 365 | '@tailwindcss/oxide-win32-arm64-msvc@4.0.9': 366 | resolution: {integrity: sha512-m3+60T/7YvWekajNq/eexjhV8z10rswcz4BC9bioJ7YaN+7K8W2AmLmG0B79H14m6UHE571qB0XsPus4n0QVgQ==} 367 | engines: {node: '>= 10'} 368 | cpu: [arm64] 369 | os: [win32] 370 | 371 | '@tailwindcss/oxide-win32-x64-msvc@4.0.9': 372 | resolution: {integrity: sha512-dpc05mSlqkwVNOUjGu/ZXd5U1XNch1kHFJ4/cHkZFvaW1RzbHmRt24gvM8/HC6IirMxNarzVw4IXVtvrOoZtxA==} 373 | engines: {node: '>= 10'} 374 | cpu: [x64] 375 | os: [win32] 376 | 377 | '@tailwindcss/oxide@4.0.9': 378 | resolution: {integrity: sha512-eLizHmXFqHswJONwfqi/WZjtmWZpIalpvMlNhTM99/bkHtUs6IqgI1XQ0/W5eO2HiRQcIlXUogI2ycvKhVLNcA==} 379 | engines: {node: '>= 10'} 380 | 381 | '@tailwindcss/postcss@4.0.9': 382 | resolution: {integrity: sha512-BT/E+pdMqulavEAVM5NCpxmGEwHiLDPpkmg/c/X25ZBW+izTe+aZ+v1gf/HXTrihRoCxrUp5U4YyHsBTzspQKQ==} 383 | 384 | '@types/node@22.13.8': 385 | resolution: {integrity: sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ==} 386 | 387 | '@types/react-dom@19.0.4': 388 | resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} 389 | peerDependencies: 390 | '@types/react': ^19.0.0 391 | 392 | '@types/react@19.0.10': 393 | resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==} 394 | 395 | busboy@1.6.0: 396 | resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} 397 | engines: {node: '>=10.16.0'} 398 | 399 | caniuse-lite@1.0.30001701: 400 | resolution: {integrity: sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==} 401 | 402 | class-variance-authority@0.7.1: 403 | resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} 404 | 405 | client-only@0.0.1: 406 | resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} 407 | 408 | clsx@2.1.1: 409 | resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} 410 | engines: {node: '>=6'} 411 | 412 | color-convert@2.0.1: 413 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 414 | engines: {node: '>=7.0.0'} 415 | 416 | color-name@1.1.4: 417 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 418 | 419 | color-string@1.9.1: 420 | resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} 421 | 422 | color@4.2.3: 423 | resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} 424 | engines: {node: '>=12.5.0'} 425 | 426 | csstype@3.1.3: 427 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 428 | 429 | detect-libc@1.0.3: 430 | resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} 431 | engines: {node: '>=0.10'} 432 | hasBin: true 433 | 434 | detect-libc@2.0.3: 435 | resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} 436 | engines: {node: '>=8'} 437 | 438 | enhanced-resolve@5.18.1: 439 | resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} 440 | engines: {node: '>=10.13.0'} 441 | 442 | graceful-fs@4.2.11: 443 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 444 | 445 | is-arrayish@0.3.2: 446 | resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} 447 | 448 | jiti@2.4.2: 449 | resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} 450 | hasBin: true 451 | 452 | lightningcss-darwin-arm64@1.29.1: 453 | resolution: {integrity: sha512-HtR5XJ5A0lvCqYAoSv2QdZZyoHNttBpa5EP9aNuzBQeKGfbyH5+UipLWvVzpP4Uml5ej4BYs5I9Lco9u1fECqw==} 454 | engines: {node: '>= 12.0.0'} 455 | cpu: [arm64] 456 | os: [darwin] 457 | 458 | lightningcss-darwin-x64@1.29.1: 459 | resolution: {integrity: sha512-k33G9IzKUpHy/J/3+9MCO4e+PzaFblsgBjSGlpAaFikeBFm8B/CkO3cKU9oI4g+fjS2KlkLM/Bza9K/aw8wsNA==} 460 | engines: {node: '>= 12.0.0'} 461 | cpu: [x64] 462 | os: [darwin] 463 | 464 | lightningcss-freebsd-x64@1.29.1: 465 | resolution: {integrity: sha512-0SUW22fv/8kln2LnIdOCmSuXnxgxVC276W5KLTwoehiO0hxkacBxjHOL5EtHD8BAXg2BvuhsJPmVMasvby3LiQ==} 466 | engines: {node: '>= 12.0.0'} 467 | cpu: [x64] 468 | os: [freebsd] 469 | 470 | lightningcss-linux-arm-gnueabihf@1.29.1: 471 | resolution: {integrity: sha512-sD32pFvlR0kDlqsOZmYqH/68SqUMPNj+0pucGxToXZi4XZgZmqeX/NkxNKCPsswAXU3UeYgDSpGhu05eAufjDg==} 472 | engines: {node: '>= 12.0.0'} 473 | cpu: [arm] 474 | os: [linux] 475 | 476 | lightningcss-linux-arm64-gnu@1.29.1: 477 | resolution: {integrity: sha512-0+vClRIZ6mmJl/dxGuRsE197o1HDEeeRk6nzycSy2GofC2JsY4ifCRnvUWf/CUBQmlrvMzt6SMQNMSEu22csWQ==} 478 | engines: {node: '>= 12.0.0'} 479 | cpu: [arm64] 480 | os: [linux] 481 | 482 | lightningcss-linux-arm64-musl@1.29.1: 483 | resolution: {integrity: sha512-UKMFrG4rL/uHNgelBsDwJcBqVpzNJbzsKkbI3Ja5fg00sgQnHw/VrzUTEc4jhZ+AN2BvQYz/tkHu4vt1kLuJyw==} 484 | engines: {node: '>= 12.0.0'} 485 | cpu: [arm64] 486 | os: [linux] 487 | 488 | lightningcss-linux-x64-gnu@1.29.1: 489 | resolution: {integrity: sha512-u1S+xdODy/eEtjADqirA774y3jLcm8RPtYztwReEXoZKdzgsHYPl0s5V52Tst+GKzqjebkULT86XMSxejzfISw==} 490 | engines: {node: '>= 12.0.0'} 491 | cpu: [x64] 492 | os: [linux] 493 | 494 | lightningcss-linux-x64-musl@1.29.1: 495 | resolution: {integrity: sha512-L0Tx0DtaNUTzXv0lbGCLB/c/qEADanHbu4QdcNOXLIe1i8i22rZRpbT3gpWYsCh9aSL9zFujY/WmEXIatWvXbw==} 496 | engines: {node: '>= 12.0.0'} 497 | cpu: [x64] 498 | os: [linux] 499 | 500 | lightningcss-win32-arm64-msvc@1.29.1: 501 | resolution: {integrity: sha512-QoOVnkIEFfbW4xPi+dpdft/zAKmgLgsRHfJalEPYuJDOWf7cLQzYg0DEh8/sn737FaeMJxHZRc1oBreiwZCjog==} 502 | engines: {node: '>= 12.0.0'} 503 | cpu: [arm64] 504 | os: [win32] 505 | 506 | lightningcss-win32-x64-msvc@1.29.1: 507 | resolution: {integrity: sha512-NygcbThNBe4JElP+olyTI/doBNGJvLs3bFCRPdvuCcxZCcCZ71B858IHpdm7L1btZex0FvCmM17FK98Y9MRy1Q==} 508 | engines: {node: '>= 12.0.0'} 509 | cpu: [x64] 510 | os: [win32] 511 | 512 | lightningcss@1.29.1: 513 | resolution: {integrity: sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==} 514 | engines: {node: '>= 12.0.0'} 515 | 516 | lucide-react@0.477.0: 517 | resolution: {integrity: sha512-yCf7aYxerFZAbd8jHJxjwe1j7jEMPptjnaOqdYeirFnEy85cNR3/L+o0I875CYFYya+eEVzZSbNuRk8BZPDpVw==} 518 | peerDependencies: 519 | react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 520 | 521 | nanoid@3.3.8: 522 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} 523 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 524 | hasBin: true 525 | 526 | next@15.3.1-canary.15: 527 | resolution: {integrity: sha512-K04SKrZ+HKrx1+rma4y9nfxilL5HnQ5KiL0biKwyQyhiG5xFLUqaHGzpiYflbWW+ufJWejk3cJJkhK/DUuB37Q==} 528 | engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} 529 | hasBin: true 530 | peerDependencies: 531 | '@opentelemetry/api': ^1.1.0 532 | '@playwright/test': ^1.41.2 533 | babel-plugin-react-compiler: '*' 534 | react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 535 | react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 536 | sass: ^1.3.0 537 | peerDependenciesMeta: 538 | '@opentelemetry/api': 539 | optional: true 540 | '@playwright/test': 541 | optional: true 542 | babel-plugin-react-compiler: 543 | optional: true 544 | sass: 545 | optional: true 546 | 547 | picocolors@1.1.1: 548 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 549 | 550 | postcss@8.4.31: 551 | resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} 552 | engines: {node: ^10 || ^12 || >=14} 553 | 554 | postcss@8.5.3: 555 | resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} 556 | engines: {node: ^10 || ^12 || >=14} 557 | 558 | react-dom@19.0.0: 559 | resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} 560 | peerDependencies: 561 | react: ^19.0.0 562 | 563 | react@19.0.0: 564 | resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} 565 | engines: {node: '>=0.10.0'} 566 | 567 | scheduler@0.25.0: 568 | resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} 569 | 570 | semver@7.7.1: 571 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 572 | engines: {node: '>=10'} 573 | hasBin: true 574 | 575 | sharp@0.34.1: 576 | resolution: {integrity: sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==} 577 | engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} 578 | 579 | simple-swizzle@0.2.2: 580 | resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} 581 | 582 | source-map-js@1.2.1: 583 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 584 | engines: {node: '>=0.10.0'} 585 | 586 | streamsearch@1.1.0: 587 | resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} 588 | engines: {node: '>=10.0.0'} 589 | 590 | styled-jsx@5.1.6: 591 | resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} 592 | engines: {node: '>= 12.0.0'} 593 | peerDependencies: 594 | '@babel/core': '*' 595 | babel-plugin-macros: '*' 596 | react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' 597 | peerDependenciesMeta: 598 | '@babel/core': 599 | optional: true 600 | babel-plugin-macros: 601 | optional: true 602 | 603 | tailwind-merge@3.0.2: 604 | resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==} 605 | 606 | tailwindcss-animate@1.0.7: 607 | resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} 608 | peerDependencies: 609 | tailwindcss: '>=3.0.0 || insiders' 610 | 611 | tailwindcss@4.0.9: 612 | resolution: {integrity: sha512-12laZu+fv1ONDRoNR9ipTOpUD7RN9essRVkX36sjxuRUInpN7hIiHN4lBd/SIFjbISvnXzp8h/hXzmU8SQQYhw==} 613 | 614 | tapable@2.2.1: 615 | resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} 616 | engines: {node: '>=6'} 617 | 618 | tslib@2.8.1: 619 | resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 620 | 621 | typescript@5.8.2: 622 | resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 623 | engines: {node: '>=14.17'} 624 | hasBin: true 625 | 626 | undici-types@6.20.0: 627 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 628 | 629 | snapshots: 630 | 631 | '@alloc/quick-lru@5.2.0': {} 632 | 633 | '@emnapi/runtime@1.4.3': 634 | dependencies: 635 | tslib: 2.8.1 636 | optional: true 637 | 638 | '@img/sharp-darwin-arm64@0.34.1': 639 | optionalDependencies: 640 | '@img/sharp-libvips-darwin-arm64': 1.1.0 641 | optional: true 642 | 643 | '@img/sharp-darwin-x64@0.34.1': 644 | optionalDependencies: 645 | '@img/sharp-libvips-darwin-x64': 1.1.0 646 | optional: true 647 | 648 | '@img/sharp-libvips-darwin-arm64@1.1.0': 649 | optional: true 650 | 651 | '@img/sharp-libvips-darwin-x64@1.1.0': 652 | optional: true 653 | 654 | '@img/sharp-libvips-linux-arm64@1.1.0': 655 | optional: true 656 | 657 | '@img/sharp-libvips-linux-arm@1.1.0': 658 | optional: true 659 | 660 | '@img/sharp-libvips-linux-ppc64@1.1.0': 661 | optional: true 662 | 663 | '@img/sharp-libvips-linux-s390x@1.1.0': 664 | optional: true 665 | 666 | '@img/sharp-libvips-linux-x64@1.1.0': 667 | optional: true 668 | 669 | '@img/sharp-libvips-linuxmusl-arm64@1.1.0': 670 | optional: true 671 | 672 | '@img/sharp-libvips-linuxmusl-x64@1.1.0': 673 | optional: true 674 | 675 | '@img/sharp-linux-arm64@0.34.1': 676 | optionalDependencies: 677 | '@img/sharp-libvips-linux-arm64': 1.1.0 678 | optional: true 679 | 680 | '@img/sharp-linux-arm@0.34.1': 681 | optionalDependencies: 682 | '@img/sharp-libvips-linux-arm': 1.1.0 683 | optional: true 684 | 685 | '@img/sharp-linux-s390x@0.34.1': 686 | optionalDependencies: 687 | '@img/sharp-libvips-linux-s390x': 1.1.0 688 | optional: true 689 | 690 | '@img/sharp-linux-x64@0.34.1': 691 | optionalDependencies: 692 | '@img/sharp-libvips-linux-x64': 1.1.0 693 | optional: true 694 | 695 | '@img/sharp-linuxmusl-arm64@0.34.1': 696 | optionalDependencies: 697 | '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 698 | optional: true 699 | 700 | '@img/sharp-linuxmusl-x64@0.34.1': 701 | optionalDependencies: 702 | '@img/sharp-libvips-linuxmusl-x64': 1.1.0 703 | optional: true 704 | 705 | '@img/sharp-wasm32@0.34.1': 706 | dependencies: 707 | '@emnapi/runtime': 1.4.3 708 | optional: true 709 | 710 | '@img/sharp-win32-ia32@0.34.1': 711 | optional: true 712 | 713 | '@img/sharp-win32-x64@0.34.1': 714 | optional: true 715 | 716 | '@next/env@15.3.1-canary.15': {} 717 | 718 | '@next/swc-darwin-arm64@15.3.1-canary.15': 719 | optional: true 720 | 721 | '@next/swc-darwin-x64@15.3.1-canary.15': 722 | optional: true 723 | 724 | '@next/swc-linux-arm64-gnu@15.3.1-canary.15': 725 | optional: true 726 | 727 | '@next/swc-linux-arm64-musl@15.3.1-canary.15': 728 | optional: true 729 | 730 | '@next/swc-linux-x64-gnu@15.3.1-canary.15': 731 | optional: true 732 | 733 | '@next/swc-linux-x64-musl@15.3.1-canary.15': 734 | optional: true 735 | 736 | '@next/swc-win32-arm64-msvc@15.3.1-canary.15': 737 | optional: true 738 | 739 | '@next/swc-win32-x64-msvc@15.3.1-canary.15': 740 | optional: true 741 | 742 | '@radix-ui/react-avatar@1.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 743 | dependencies: 744 | '@radix-ui/react-context': 1.1.1(@types/react@19.0.10)(react@19.0.0) 745 | '@radix-ui/react-primitive': 2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) 746 | '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.10)(react@19.0.0) 747 | '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.10)(react@19.0.0) 748 | react: 19.0.0 749 | react-dom: 19.0.0(react@19.0.0) 750 | optionalDependencies: 751 | '@types/react': 19.0.10 752 | '@types/react-dom': 19.0.4(@types/react@19.0.10) 753 | 754 | '@radix-ui/react-compose-refs@1.1.1(@types/react@19.0.10)(react@19.0.0)': 755 | dependencies: 756 | react: 19.0.0 757 | optionalDependencies: 758 | '@types/react': 19.0.10 759 | 760 | '@radix-ui/react-context@1.1.1(@types/react@19.0.10)(react@19.0.0)': 761 | dependencies: 762 | react: 19.0.0 763 | optionalDependencies: 764 | '@types/react': 19.0.10 765 | 766 | '@radix-ui/react-primitive@2.0.2(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': 767 | dependencies: 768 | '@radix-ui/react-slot': 1.1.2(@types/react@19.0.10)(react@19.0.0) 769 | react: 19.0.0 770 | react-dom: 19.0.0(react@19.0.0) 771 | optionalDependencies: 772 | '@types/react': 19.0.10 773 | '@types/react-dom': 19.0.4(@types/react@19.0.10) 774 | 775 | '@radix-ui/react-slot@1.1.2(@types/react@19.0.10)(react@19.0.0)': 776 | dependencies: 777 | '@radix-ui/react-compose-refs': 1.1.1(@types/react@19.0.10)(react@19.0.0) 778 | react: 19.0.0 779 | optionalDependencies: 780 | '@types/react': 19.0.10 781 | 782 | '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.10)(react@19.0.0)': 783 | dependencies: 784 | react: 19.0.0 785 | optionalDependencies: 786 | '@types/react': 19.0.10 787 | 788 | '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.10)(react@19.0.0)': 789 | dependencies: 790 | react: 19.0.0 791 | optionalDependencies: 792 | '@types/react': 19.0.10 793 | 794 | '@swc/counter@0.1.3': {} 795 | 796 | '@swc/helpers@0.5.15': 797 | dependencies: 798 | tslib: 2.8.1 799 | 800 | '@tailwindcss/node@4.0.9': 801 | dependencies: 802 | enhanced-resolve: 5.18.1 803 | jiti: 2.4.2 804 | tailwindcss: 4.0.9 805 | 806 | '@tailwindcss/oxide-android-arm64@4.0.9': 807 | optional: true 808 | 809 | '@tailwindcss/oxide-darwin-arm64@4.0.9': 810 | optional: true 811 | 812 | '@tailwindcss/oxide-darwin-x64@4.0.9': 813 | optional: true 814 | 815 | '@tailwindcss/oxide-freebsd-x64@4.0.9': 816 | optional: true 817 | 818 | '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.9': 819 | optional: true 820 | 821 | '@tailwindcss/oxide-linux-arm64-gnu@4.0.9': 822 | optional: true 823 | 824 | '@tailwindcss/oxide-linux-arm64-musl@4.0.9': 825 | optional: true 826 | 827 | '@tailwindcss/oxide-linux-x64-gnu@4.0.9': 828 | optional: true 829 | 830 | '@tailwindcss/oxide-linux-x64-musl@4.0.9': 831 | optional: true 832 | 833 | '@tailwindcss/oxide-win32-arm64-msvc@4.0.9': 834 | optional: true 835 | 836 | '@tailwindcss/oxide-win32-x64-msvc@4.0.9': 837 | optional: true 838 | 839 | '@tailwindcss/oxide@4.0.9': 840 | optionalDependencies: 841 | '@tailwindcss/oxide-android-arm64': 4.0.9 842 | '@tailwindcss/oxide-darwin-arm64': 4.0.9 843 | '@tailwindcss/oxide-darwin-x64': 4.0.9 844 | '@tailwindcss/oxide-freebsd-x64': 4.0.9 845 | '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.9 846 | '@tailwindcss/oxide-linux-arm64-gnu': 4.0.9 847 | '@tailwindcss/oxide-linux-arm64-musl': 4.0.9 848 | '@tailwindcss/oxide-linux-x64-gnu': 4.0.9 849 | '@tailwindcss/oxide-linux-x64-musl': 4.0.9 850 | '@tailwindcss/oxide-win32-arm64-msvc': 4.0.9 851 | '@tailwindcss/oxide-win32-x64-msvc': 4.0.9 852 | 853 | '@tailwindcss/postcss@4.0.9': 854 | dependencies: 855 | '@alloc/quick-lru': 5.2.0 856 | '@tailwindcss/node': 4.0.9 857 | '@tailwindcss/oxide': 4.0.9 858 | lightningcss: 1.29.1 859 | postcss: 8.5.3 860 | tailwindcss: 4.0.9 861 | 862 | '@types/node@22.13.8': 863 | dependencies: 864 | undici-types: 6.20.0 865 | 866 | '@types/react-dom@19.0.4(@types/react@19.0.10)': 867 | dependencies: 868 | '@types/react': 19.0.10 869 | 870 | '@types/react@19.0.10': 871 | dependencies: 872 | csstype: 3.1.3 873 | 874 | busboy@1.6.0: 875 | dependencies: 876 | streamsearch: 1.1.0 877 | 878 | caniuse-lite@1.0.30001701: {} 879 | 880 | class-variance-authority@0.7.1: 881 | dependencies: 882 | clsx: 2.1.1 883 | 884 | client-only@0.0.1: {} 885 | 886 | clsx@2.1.1: {} 887 | 888 | color-convert@2.0.1: 889 | dependencies: 890 | color-name: 1.1.4 891 | optional: true 892 | 893 | color-name@1.1.4: 894 | optional: true 895 | 896 | color-string@1.9.1: 897 | dependencies: 898 | color-name: 1.1.4 899 | simple-swizzle: 0.2.2 900 | optional: true 901 | 902 | color@4.2.3: 903 | dependencies: 904 | color-convert: 2.0.1 905 | color-string: 1.9.1 906 | optional: true 907 | 908 | csstype@3.1.3: {} 909 | 910 | detect-libc@1.0.3: {} 911 | 912 | detect-libc@2.0.3: 913 | optional: true 914 | 915 | enhanced-resolve@5.18.1: 916 | dependencies: 917 | graceful-fs: 4.2.11 918 | tapable: 2.2.1 919 | 920 | graceful-fs@4.2.11: {} 921 | 922 | is-arrayish@0.3.2: 923 | optional: true 924 | 925 | jiti@2.4.2: {} 926 | 927 | lightningcss-darwin-arm64@1.29.1: 928 | optional: true 929 | 930 | lightningcss-darwin-x64@1.29.1: 931 | optional: true 932 | 933 | lightningcss-freebsd-x64@1.29.1: 934 | optional: true 935 | 936 | lightningcss-linux-arm-gnueabihf@1.29.1: 937 | optional: true 938 | 939 | lightningcss-linux-arm64-gnu@1.29.1: 940 | optional: true 941 | 942 | lightningcss-linux-arm64-musl@1.29.1: 943 | optional: true 944 | 945 | lightningcss-linux-x64-gnu@1.29.1: 946 | optional: true 947 | 948 | lightningcss-linux-x64-musl@1.29.1: 949 | optional: true 950 | 951 | lightningcss-win32-arm64-msvc@1.29.1: 952 | optional: true 953 | 954 | lightningcss-win32-x64-msvc@1.29.1: 955 | optional: true 956 | 957 | lightningcss@1.29.1: 958 | dependencies: 959 | detect-libc: 1.0.3 960 | optionalDependencies: 961 | lightningcss-darwin-arm64: 1.29.1 962 | lightningcss-darwin-x64: 1.29.1 963 | lightningcss-freebsd-x64: 1.29.1 964 | lightningcss-linux-arm-gnueabihf: 1.29.1 965 | lightningcss-linux-arm64-gnu: 1.29.1 966 | lightningcss-linux-arm64-musl: 1.29.1 967 | lightningcss-linux-x64-gnu: 1.29.1 968 | lightningcss-linux-x64-musl: 1.29.1 969 | lightningcss-win32-arm64-msvc: 1.29.1 970 | lightningcss-win32-x64-msvc: 1.29.1 971 | 972 | lucide-react@0.477.0(react@19.0.0): 973 | dependencies: 974 | react: 19.0.0 975 | 976 | nanoid@3.3.8: {} 977 | 978 | next@15.3.1-canary.15(react-dom@19.0.0(react@19.0.0))(react@19.0.0): 979 | dependencies: 980 | '@next/env': 15.3.1-canary.15 981 | '@swc/counter': 0.1.3 982 | '@swc/helpers': 0.5.15 983 | busboy: 1.6.0 984 | caniuse-lite: 1.0.30001701 985 | postcss: 8.4.31 986 | react: 19.0.0 987 | react-dom: 19.0.0(react@19.0.0) 988 | styled-jsx: 5.1.6(react@19.0.0) 989 | optionalDependencies: 990 | '@next/swc-darwin-arm64': 15.3.1-canary.15 991 | '@next/swc-darwin-x64': 15.3.1-canary.15 992 | '@next/swc-linux-arm64-gnu': 15.3.1-canary.15 993 | '@next/swc-linux-arm64-musl': 15.3.1-canary.15 994 | '@next/swc-linux-x64-gnu': 15.3.1-canary.15 995 | '@next/swc-linux-x64-musl': 15.3.1-canary.15 996 | '@next/swc-win32-arm64-msvc': 15.3.1-canary.15 997 | '@next/swc-win32-x64-msvc': 15.3.1-canary.15 998 | sharp: 0.34.1 999 | transitivePeerDependencies: 1000 | - '@babel/core' 1001 | - babel-plugin-macros 1002 | 1003 | picocolors@1.1.1: {} 1004 | 1005 | postcss@8.4.31: 1006 | dependencies: 1007 | nanoid: 3.3.8 1008 | picocolors: 1.1.1 1009 | source-map-js: 1.2.1 1010 | 1011 | postcss@8.5.3: 1012 | dependencies: 1013 | nanoid: 3.3.8 1014 | picocolors: 1.1.1 1015 | source-map-js: 1.2.1 1016 | 1017 | react-dom@19.0.0(react@19.0.0): 1018 | dependencies: 1019 | react: 19.0.0 1020 | scheduler: 0.25.0 1021 | 1022 | react@19.0.0: {} 1023 | 1024 | scheduler@0.25.0: {} 1025 | 1026 | semver@7.7.1: 1027 | optional: true 1028 | 1029 | sharp@0.34.1: 1030 | dependencies: 1031 | color: 4.2.3 1032 | detect-libc: 2.0.3 1033 | semver: 7.7.1 1034 | optionalDependencies: 1035 | '@img/sharp-darwin-arm64': 0.34.1 1036 | '@img/sharp-darwin-x64': 0.34.1 1037 | '@img/sharp-libvips-darwin-arm64': 1.1.0 1038 | '@img/sharp-libvips-darwin-x64': 1.1.0 1039 | '@img/sharp-libvips-linux-arm': 1.1.0 1040 | '@img/sharp-libvips-linux-arm64': 1.1.0 1041 | '@img/sharp-libvips-linux-ppc64': 1.1.0 1042 | '@img/sharp-libvips-linux-s390x': 1.1.0 1043 | '@img/sharp-libvips-linux-x64': 1.1.0 1044 | '@img/sharp-libvips-linuxmusl-arm64': 1.1.0 1045 | '@img/sharp-libvips-linuxmusl-x64': 1.1.0 1046 | '@img/sharp-linux-arm': 0.34.1 1047 | '@img/sharp-linux-arm64': 0.34.1 1048 | '@img/sharp-linux-s390x': 0.34.1 1049 | '@img/sharp-linux-x64': 0.34.1 1050 | '@img/sharp-linuxmusl-arm64': 0.34.1 1051 | '@img/sharp-linuxmusl-x64': 0.34.1 1052 | '@img/sharp-wasm32': 0.34.1 1053 | '@img/sharp-win32-ia32': 0.34.1 1054 | '@img/sharp-win32-x64': 0.34.1 1055 | optional: true 1056 | 1057 | simple-swizzle@0.2.2: 1058 | dependencies: 1059 | is-arrayish: 0.3.2 1060 | optional: true 1061 | 1062 | source-map-js@1.2.1: {} 1063 | 1064 | streamsearch@1.1.0: {} 1065 | 1066 | styled-jsx@5.1.6(react@19.0.0): 1067 | dependencies: 1068 | client-only: 0.0.1 1069 | react: 19.0.0 1070 | 1071 | tailwind-merge@3.0.2: {} 1072 | 1073 | tailwindcss-animate@1.0.7(tailwindcss@4.0.9): 1074 | dependencies: 1075 | tailwindcss: 4.0.9 1076 | 1077 | tailwindcss@4.0.9: {} 1078 | 1079 | tapable@2.2.1: {} 1080 | 1081 | tslib@2.8.1: {} 1082 | 1083 | typescript@5.8.2: {} 1084 | 1085 | undici-types@6.20.0: {} 1086 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | const config = { 2 | plugins: ["@tailwindcss/postcss"], 3 | }; 4 | 5 | export default config; 6 | -------------------------------------------------------------------------------- /public/avatars/feedthejim.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/avatars/feedthejim.jpg -------------------------------------------------------------------------------- /public/avatars/huozhi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/avatars/huozhi.jpg -------------------------------------------------------------------------------- /public/avatars/leerob.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/avatars/leerob.jpg -------------------------------------------------------------------------------- /public/avatars/sebmarkbage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/avatars/sebmarkbage.jpg -------------------------------------------------------------------------------- /public/avatars/ztanner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/avatars/ztanner.jpg -------------------------------------------------------------------------------- /public/cards/barcelona.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/cards/barcelona.png -------------------------------------------------------------------------------- /public/cards/florence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/cards/florence.png -------------------------------------------------------------------------------- /public/cards/santamonica.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/cards/santamonica.png -------------------------------------------------------------------------------- /public/cards/xian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/cards/xian.png -------------------------------------------------------------------------------- /public/post/composable-caching-with-nextjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel/next-view-transition-example/9d21a7b8ace73bb67aa1b301570f3a0cae405d70/public/post/composable-caching-with-nextjs.png -------------------------------------------------------------------------------- /tailwind.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "tailwindcss"; 2 | 3 | const config: Config = { 4 | content: [ 5 | "./pages/**/*.{js,ts,jsx,tsx,mdx}", 6 | "./components/**/*.{js,ts,jsx,tsx,mdx}", 7 | "./app/**/*.{js,ts,jsx,tsx,mdx}", 8 | ], 9 | theme: { 10 | extend: { 11 | colors: { 12 | background: 'hsl(var(--background))', 13 | foreground: 'hsl(var(--foreground))', 14 | card: { 15 | DEFAULT: 'hsl(var(--card))', 16 | foreground: 'hsl(var(--card-foreground))' 17 | }, 18 | popover: { 19 | DEFAULT: 'hsl(var(--popover))', 20 | foreground: 'hsl(var(--popover-foreground))' 21 | }, 22 | primary: { 23 | DEFAULT: 'hsl(var(--primary))', 24 | foreground: 'hsl(var(--primary-foreground))' 25 | }, 26 | secondary: { 27 | DEFAULT: 'hsl(var(--secondary))', 28 | foreground: 'hsl(var(--secondary-foreground))' 29 | }, 30 | muted: { 31 | DEFAULT: 'hsl(var(--muted))', 32 | foreground: 'hsl(var(--muted-foreground))' 33 | }, 34 | accent: { 35 | DEFAULT: 'hsl(var(--accent))', 36 | foreground: 'hsl(var(--accent-foreground))' 37 | }, 38 | destructive: { 39 | DEFAULT: 'hsl(var(--destructive))', 40 | foreground: 'hsl(var(--destructive-foreground))' 41 | }, 42 | border: 'hsl(var(--border))', 43 | input: 'hsl(var(--input))', 44 | ring: 'hsl(var(--ring))', 45 | chart: { 46 | '1': 'hsl(var(--chart-1))', 47 | '2': 'hsl(var(--chart-2))', 48 | '3': 'hsl(var(--chart-3))', 49 | '4': 'hsl(var(--chart-4))', 50 | '5': 'hsl(var(--chart-5))' 51 | } 52 | }, 53 | borderRadius: { 54 | lg: 'var(--radius)', 55 | md: 'calc(var(--radius) - 2px)', 56 | sm: 'calc(var(--radius) - 4px)' 57 | } 58 | } 59 | }, 60 | plugins: [require("tailwindcss-animate")], 61 | }; 62 | export default config; 63 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | --------------------------------------------------------------------------------