[ci] format

This commit is contained in:
matthewp 2023-09-27 19:25:02 +00:00 committed by astrobot-houston
parent e6be2d8146
commit a10a798c18
35 changed files with 83947 additions and 485 deletions

View file

@ -1,4 +1,4 @@
import { defineConfig } from 'astro/config'
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
import nodejs from '@astrojs/node';
@ -12,4 +12,4 @@ export default defineConfig({
'process.env.TMDB_API_KEY': JSON.stringify(process.env.TMDB_API_KEY),
},
},
})
});

View file

@ -4,16 +4,24 @@ const { movie } = Astro.props;
<div class="mt-8">
<a href={`/movies/${movie.id}`}>
<img src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
<img
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
alt={`${movie.title} Poster`}
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
id={`movie-poster-${movie.id}`}
transition:name={`poster-${movie.id}`}>
transition:name={`poster-${movie.id}`}
/>
</a>
<div class="mt-2">
<a href={`/movies/${movie.id}`} class="text-lg mt-2 hover:text-gray-300">{movie.title}</a>
<div class="flex items-center text-gray-400 text-sm mt-1">
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"><g data-name="Layer 2"><path d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z" data-name="star"/></g></svg>
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
><g data-name="Layer 2"
><path
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
data-name="star"></path></g
></svg
>
<span class="ml-1">{movie.vote_average}</span>
<span class="mx-2">|</span>
<span>{movie.release_date}</span>

View file

@ -10,7 +10,7 @@ const movie = {
release_date: new Date(data.release_date).toLocaleDateString('en-us', {
year: 'numeric',
month: 'long',
day: 'numeric'
day: 'numeric',
}),
genres: data.genres.map((g: any) => g.name).join(', '),
crew: data.credits.crew.slice(0, 3),
@ -18,25 +18,33 @@ const movie = {
...c,
profile_path: c.profile_path
? 'https://image.tmdb.org/t/p/w300/' + c.profile_path
: 'https://via.placeholder.com/300x450'
: 'https://via.placeholder.com/300x450',
})),
images: data.images.backdrops.slice(0, 9),
}
};
---
<div class="movie-info border-b border-gray-800">
<div class="container mx-auto px-4 py-16 flex flex-col md:flex-row">
<div class="flex-none">
<img src={movie.poster_path}
<img
src={movie.poster_path}
alt={`${movie.title} Poster`}
class="movie-poster w-64 lg:w-96"
id="movie-poster"
transition:name={`poster-${movie.id}`}>
transition:name={`poster-${movie.id}`}
/>
</div>
<div class="md:ml-24">
<h2 class="text-4xl mt-4 md:mt-0 mb-2 font-semibold">{movie.title}</h2>
<div class="flex flex-wrap items-center text-gray-400 text-sm">
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"><g data-name="Layer 2"><path d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z" data-name="star"/></g></svg>
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
><g data-name="Layer 2"
><path
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
data-name="star"></path></g
></svg
>
<span class="ml-1">{movie.vote_average}</span>
<span class="mx-2">|</span>
<span>{movie.release_date}</span>
@ -51,50 +59,67 @@ const movie = {
<div class="mt-12">
<h4 class="text-white font-semibold">Featured Crew</h4>
<div class="flex mt-4">
{movie.crew.map((crew: any) => (
{
movie.crew.map((crew: any) => (
<div class="mr-8">
<div>{crew.name}</div>
<div class="text-gray-400 text-sm">{crew.job}</div>
</div>
))}
))
}
</div>
</div>
</div>
</div>
</div> <!-- end movie-info -->
</div>
<!-- end movie-info -->
<div class="movie-cast border-b border-gray-800">
<div class="container mx-auto px-4 py-16">
<h2 class="text-4xl font-semibold">Cast</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
{movie.cast.map((cast: any) => (
{
movie.cast.map((cast: any) => (
<div class="mt-8">
<span>
<img id={`person-photo-${cast.id}`} src={cast.profile_path} alt={cast.name} class="thumbnail hover:opacity-75 transition ease-in-out duration-150">
<img
id={`person-photo-${cast.id}`}
src={cast.profile_path}
alt={cast.name}
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
/>
</span>
<div class="mt-2">
<span class="text-lg mt-2 hover:text-gray:300">{cast.name}</span>
<div class="text-sm text-gray-400">
{cast.character}
<div class="text-sm text-gray-400">{cast.character}</div>
</div>
</div>
))
}
</div>
</div>
</div>
))}
</div>
</div>
</div> <!-- end movie-cast -->
<!-- end movie-cast -->
<div class="movie-images">
<div class="container mx-auto px-4 py-16">
<h2 class="text-4xl font-semibold">Images</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
{movie.images.map((image: any) => (
{
movie.images.map((image: any) => (
<div class="mt-8">
<span>
<img src={`https://image.tmdb.org/t/p/w500${image.file_path}`} loading="lazy" alt={movie.name} class="hover:opacity-75 transition ease-in-out duration-150">
<img
src={`https://image.tmdb.org/t/p/w500${image.file_path}`}
loading="lazy"
alt={movie.name}
class="hover:opacity-75 transition ease-in-out duration-150"
/>
</span>
</div>
))}
))
}
</div>
</div>
</div> <!-- end movie-images -->
</div>
<!-- end movie-images -->

View file

@ -6,12 +6,8 @@ const popularMovies = movies.results;
<div class="container mx-auto px-4 pt-16 mb-16">
<div class="popular-movies">
<h2 class="uppercase tracking-wider text-orange-500 text-lg font-semibold">
Popular Movies
</h2>
<div
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8"
>
<h2 class="uppercase tracking-wider text-orange-500 text-lg font-semibold">Popular Movies</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
{popularMovies.map((movie) => <MovieCard movie={movie} />)}
</div>
</div>

View file

@ -1,5 +1,7 @@
<nav class="nav border-b border-gray-800 sticky top-0 z-30 bg-gray-900">
<div class="container mx-auto px-4 flex flex-col md:flex-row items-center justify-between px-4 py-6">
<div
class="container mx-auto px-4 flex flex-col md:flex-row items-center justify-between px-4 py-6"
>
<ul class="flex flex-col md:flex-row items-center">
<li>
<a href="/" class="flex items-center font-bold text-xl">

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,8 @@
---
import '../styles/styles.css';
import { ViewTransitions } from 'astro:transitions';
import Footer from "../components/Footer.astro";
import Nav from "../components/Nav.astro";
import Footer from '../components/Footer.astro';
import Nav from '../components/Nav.astro';
export interface Props {
title: string;
@ -11,7 +11,7 @@ export interface Props {
const { title } = Astro.props as Props;
---
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,7 @@ import {
shouldNotIntercept,
updateTheDOMSomehow,
useTvFragment,
} from './utils'
} from './utils';
// View Transitions support cross-document navigations.
// Should compare performace.
@ -16,44 +16,36 @@ function shouldDisableSpa() {
}
navigation.addEventListener('navigate', (navigateEvent) => {
if (shouldDisableSpa()) return
if (shouldNotIntercept(navigateEvent)) return
if (shouldDisableSpa()) return;
if (shouldNotIntercept(navigateEvent)) return;
const toUrl = new URL(navigateEvent.destination.url)
const toPath = toUrl.pathname
const fromPath = location.pathname
const navigationType = getNavigationType(fromPath, toPath)
const toUrl = new URL(navigateEvent.destination.url);
const toPath = toUrl.pathname;
const fromPath = location.pathname;
const navigationType = getNavigationType(fromPath, toPath);
if (location.origin !== toUrl.origin) return
if (location.origin !== toUrl.origin) return;
switch (navigationType) {
case 'home-to-movie':
case 'tv-to-show':
handleHomeToMovieTransition(navigateEvent, getPathId(toPath))
break
handleHomeToMovieTransition(navigateEvent, getPathId(toPath));
break;
case 'movie-to-home':
case 'show-to-tv':
handleMovieToHomeTransition(navigateEvent, getPathId(fromPath))
break
handleMovieToHomeTransition(navigateEvent, getPathId(fromPath));
break;
case 'movie-to-person':
handleMovieToPersonTransition(
navigateEvent,
getPathId(fromPath),
getPathId(toPath)
)
break
handleMovieToPersonTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
break;
case 'person-to-movie':
case 'person-to-show':
handlePersonToMovieTransition(
navigateEvent,
getPathId(fromPath),
getPathId(toPath)
)
break
handlePersonToMovieTransition(navigateEvent, getPathId(fromPath), getPathId(toPath));
break;
default:
return
return;
}
})
});
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#transitions-as-an-enhancement
function handleHomeToMovieTransition(navigateEvent, movieId) {
@ -61,31 +53,31 @@ function handleHomeToMovieTransition(navigateEvent, movieId) {
async handler() {
const fragmentUrl = useTvFragment(navigateEvent)
? '/fragments/TvDetails'
: '/fragments/MovieDetails'
const response = await fetch(`${fragmentUrl}/${movieId}`)
const data = await response.text()
: '/fragments/MovieDetails';
const response = await fetch(`${fragmentUrl}/${movieId}`);
const data = await response.text();
if (!document.startViewTransition) {
updateTheDOMSomehow(data);
return;
}
const thumbnail = document.getElementById(`movie-poster-${movieId}`)
const thumbnail = document.getElementById(`movie-poster-${movieId}`);
if (thumbnail) {
thumbnail.style.viewTransitionName = 'movie-poster'
thumbnail.style.viewTransitionName = 'movie-poster';
}
const transition = document.startViewTransition(() => {
if (thumbnail) {
thumbnail.style.viewTransitionName = ''
thumbnail.style.viewTransitionName = '';
}
document.getElementById('container').scrollTop = 0
updateTheDOMSomehow(data)
})
document.getElementById('container').scrollTop = 0;
updateTheDOMSomehow(data);
});
await transition.finished
await transition.finished;
},
})
});
}
function handleMovieToHomeTransition(navigateEvent, movieId) {
@ -94,169 +86,169 @@ function handleMovieToHomeTransition(navigateEvent, movieId) {
async handler() {
const fragmentUrl = useTvFragment(navigateEvent)
? '/fragments/TvList'
: '/fragments/MovieList'
const response = await fetch(fragmentUrl)
const data = await response.text()
: '/fragments/MovieList';
const response = await fetch(fragmentUrl);
const data = await response.text();
if (!document.startViewTransition) {
updateTheDOMSomehow(data)
return
updateTheDOMSomehow(data);
return;
}
const tempHomePage = document.createElement('div')
const moviePoster = document.getElementById(`movie-poster`)
let thumbnail
const tempHomePage = document.createElement('div');
const moviePoster = document.getElementById(`movie-poster`);
let thumbnail;
// If the movie poster is not in the home page, removes the transition style so that
// the poster doesn't stay on the page while transitioning
tempHomePage.innerHTML = data
tempHomePage.innerHTML = data;
if (!tempHomePage.querySelector(`#movie-poster-${movieId}`)) {
moviePoster?.classList.remove('movie-poster')
moviePoster?.classList.remove('movie-poster');
}
const transition = document.startViewTransition(() => {
updateTheDOMSomehow(data)
updateTheDOMSomehow(data);
thumbnail = document.getElementById(`movie-poster-${movieId}`)
thumbnail = document.getElementById(`movie-poster-${movieId}`);
if (thumbnail) {
thumbnail.scrollIntoViewIfNeeded()
thumbnail.style.viewTransitionName = 'movie-poster'
thumbnail.scrollIntoViewIfNeeded();
thumbnail.style.viewTransitionName = 'movie-poster';
}
})
});
await transition.finished
await transition.finished;
if (thumbnail) {
thumbnail.style.viewTransitionName = ''
thumbnail.style.viewTransitionName = '';
}
},
})
});
}
function handleMovieToPersonTransition(navigateEvent, movieId, personId) {
// TODO: https://developer.chrome.com/docs/web-platform/view-transitions/#not-a-polyfill
// ...has example of `back-transition` class applied to document
const isBack = isBackNavigation(navigateEvent)
const isBack = isBackNavigation(navigateEvent);
navigateEvent.intercept({
async handler() {
const response = await fetch('/fragments/PersonDetails/' + personId)
const data = await response.text()
const response = await fetch('/fragments/PersonDetails/' + personId);
const data = await response.text();
if (!document.startViewTransition) {
updateTheDOMSomehow(data)
return
updateTheDOMSomehow(data);
return;
}
let personThumbnail
let moviePoster
let movieThumbnail
let personThumbnail;
let moviePoster;
let movieThumbnail;
if (!isBack) {
// We're transitioning the person photo; we need to remove the transition of the poster
// so that it doesn't stay on the page while transitioning
moviePoster = document.getElementById(`movie-poster`)
moviePoster = document.getElementById(`movie-poster`);
if (moviePoster) {
moviePoster.classList.remove('movie-poster')
moviePoster.classList.remove('movie-poster');
}
personThumbnail = document.getElementById(`person-photo-${personId}`)
personThumbnail = document.getElementById(`person-photo-${personId}`);
if (personThumbnail) {
personThumbnail.style.viewTransitionName = 'person-photo'
personThumbnail.style.viewTransitionName = 'person-photo';
}
}
const transition = document.startViewTransition(() => {
updateTheDOMSomehow(data)
updateTheDOMSomehow(data);
if (personThumbnail) {
personThumbnail.style.viewTransitionName = ''
personThumbnail.style.viewTransitionName = '';
}
if (isBack) {
// If we're coming back to the person page, we're transitioning
// into the movie poster thumbnail, so we need to add the tag to it
movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
if (movieThumbnail) {
movieThumbnail.scrollIntoViewIfNeeded()
movieThumbnail.style.viewTransitionName = 'movie-poster'
movieThumbnail.scrollIntoViewIfNeeded();
movieThumbnail.style.viewTransitionName = 'movie-poster';
}
}
document.getElementById('container').scrollTop = 0
})
document.getElementById('container').scrollTop = 0;
});
await transition.finished
await transition.finished;
if (movieThumbnail) {
movieThumbnail.style.viewTransitionName = ''
movieThumbnail.style.viewTransitionName = '';
}
},
})
});
}
function handlePersonToMovieTransition(navigateEvent, personId, movieId) {
const isBack = isBackNavigation(navigateEvent)
const isBack = isBackNavigation(navigateEvent);
navigateEvent.intercept({
scroll: 'manual',
async handler() {
const fragmentUrl = useTvFragment(navigateEvent)
? '/fragments/TvDetails'
: '/fragments/MovieDetails'
const response = await fetch(`${fragmentUrl}/${movieId}`)
const data = await response.text()
: '/fragments/MovieDetails';
const response = await fetch(`${fragmentUrl}/${movieId}`);
const data = await response.text();
if (!document.startViewTransition) {
updateTheDOMSomehow(data)
return
updateTheDOMSomehow(data);
return;
}
let thumbnail
let moviePoster
let movieThumbnail
let thumbnail;
let moviePoster;
let movieThumbnail;
if (!isBack) {
movieThumbnail = document.getElementById(`movie-poster-${movieId}`)
movieThumbnail = document.getElementById(`movie-poster-${movieId}`);
if (movieThumbnail) {
movieThumbnail.style.viewTransitionName = 'movie-poster'
movieThumbnail.style.viewTransitionName = 'movie-poster';
}
}
const transition = document.startViewTransition(() => {
updateTheDOMSomehow(data)
updateTheDOMSomehow(data);
if (isBack) {
moviePoster = document.getElementById(`movie-poster`)
moviePoster = document.getElementById(`movie-poster`);
if (moviePoster) {
moviePoster.classList.remove('movie-poster')
moviePoster.classList.remove('movie-poster');
}
if (personId) {
thumbnail = document.getElementById(`person-photo-${personId}`)
thumbnail = document.getElementById(`person-photo-${personId}`);
if (thumbnail) {
thumbnail.scrollIntoViewIfNeeded()
thumbnail.style.viewTransitionName = 'person-photo'
thumbnail.scrollIntoViewIfNeeded();
thumbnail.style.viewTransitionName = 'person-photo';
}
}
} else {
document.getElementById('container').scrollTop = 0
document.getElementById('container').scrollTop = 0;
if (movieThumbnail) {
movieThumbnail.style.viewTransitionName = ''
movieThumbnail.style.viewTransitionName = '';
}
}
})
});
await transition.finished
await transition.finished;
if (thumbnail) {
thumbnail.style.viewTransitionName = ''
thumbnail.style.viewTransitionName = '';
}
if (moviePoster) {
moviePoster.classList.add('movie-poster')
moviePoster.classList.add('movie-poster');
}
},
})
});
}

View file

@ -1,51 +1,48 @@
export function getNavigationType(fromPath, toPath) {
if (fromPath.startsWith('/movies') && toPath === '/') {
return 'movie-to-home'
return 'movie-to-home';
}
if (fromPath === '/tv' && toPath.startsWith('/tv/')) {
return 'tv-to-show'
return 'tv-to-show';
}
if (fromPath === '/' && toPath.startsWith('/movies')) {
return 'home-to-movie'
return 'home-to-movie';
}
if (fromPath.startsWith('/tv/') && toPath === '/tv') {
return 'show-to-tv'
return 'show-to-tv';
}
if (
(fromPath.startsWith('/movies') || fromPath.startsWith('/tv')) &&
toPath.startsWith('/people')
) {
return 'movie-to-person'
return 'movie-to-person';
}
if (
fromPath.startsWith('/people') &&
(toPath.startsWith('/movies') || toPath.startsWith('/tv/'))
) {
return 'person-to-movie'
return 'person-to-movie';
}
return 'other'
return 'other';
}
export function isBackNavigation(navigateEvent) {
if (
navigateEvent.navigationType === 'push' ||
navigateEvent.navigationType === 'replace'
) {
return false
if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
return false;
}
if (
navigateEvent.destination.index !== -1 &&
navigateEvent.destination.index < navigation.currentEntry.index
) {
return true
return true;
}
return false
return false;
}
export function shouldNotIntercept(navigationEvent) {
@ -60,20 +57,20 @@ export function shouldNotIntercept(navigationEvent) {
// If this is a form submission,
// let that go to the server.
navigationEvent.formData
)
);
}
export function useTvFragment(navigateEvent) {
const toUrl = new URL(navigateEvent.destination.url)
const toPath = toUrl.pathname
const toUrl = new URL(navigateEvent.destination.url);
const toPath = toUrl.pathname;
return toPath.startsWith('/tv')
return toPath.startsWith('/tv');
}
export function getPathId(path) {
return path.split('/')[2]
return path.split('/')[2];
}
export function updateTheDOMSomehow(data) {
document.getElementById('content').innerHTML = data
document.getElementById('content').innerHTML = data;
}

View file

@ -23,12 +23,14 @@
}
::view-transition-old(root) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
animation:
90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(root) {
animation: 210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
animation:
210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}

View file

@ -9,4 +9,4 @@ module.exports = {
},
},
plugins: [],
}
};

View file

@ -24,16 +24,21 @@ const announce = () => {
let div = document.createElement('div');
div.setAttribute('aria-live', 'assertive');
div.setAttribute('aria-atomic', 'true');
div.setAttribute('style', 'position:absolute;left:0;top:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px');
div.setAttribute(
'style',
'position:absolute;left:0;top:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;width:1px;height:1px'
);
document.body.append(div);
setTimeout(() => {
setTimeout(
() => {
let title = document.title || document.querySelector('h1')?.textContent || location.pathname;
div.textContent = title;
},
// Much thought went into this magic number; the gist is that screen readers
// need to see that the element changed and might not do so if it happens
// too quickly.
60);
60
);
};
const PERSIST_ATTR = 'data-astro-transition-persist';
const parser = new DOMParser();