diff --git a/package.json b/package.json index d9d032e8..ba76608d 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "nanoid": "^5.0.6", - "next": "14.1.1-canary.70", - "next-auth": "5.0.0-beta.9", + "next": "14.1.1-canary.71", + "next-auth": "5.0.0-beta.13", "next-themes": "^0.2.1", "postcss": "8.4.35", "react": "18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6d5b5f9..4755ab40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,7 +46,7 @@ dependencies: version: 7.0.2(eslint@8.56.0)(typescript@5.3.3) '@vercel/analytics': specifier: ^1.2.2 - version: 1.2.2(next@14.1.1-canary.70)(react@18.2.0) + version: 1.2.2(next@14.1.1-canary.71)(react@18.2.0) '@vercel/blob': specifier: ^0.22.1 version: 0.22.1 @@ -55,7 +55,7 @@ dependencies: version: 0.7.2 '@vercel/speed-insights': specifier: ^1.0.10 - version: 1.0.10(next@14.1.1-canary.70)(react@18.2.0) + version: 1.0.10(next@14.1.1-canary.71)(react@18.2.0) autoprefixer: specifier: 10.4.17 version: 10.4.17(postcss@8.4.35) @@ -93,14 +93,14 @@ dependencies: specifier: ^5.0.6 version: 5.0.6 next: - specifier: 14.1.1-canary.70 - version: 14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + specifier: 14.1.1-canary.71 + version: 14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) next-auth: - specifier: 5.0.0-beta.9 - version: 5.0.0-beta.9(next@14.1.1-canary.70)(react@18.2.0) + specifier: 5.0.0-beta.13 + version: 5.0.0-beta.13(next@14.1.1-canary.71)(react@18.2.0) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.1.1-canary.70)(react-dom@18.2.0)(react@18.2.0) + version: 0.2.1(next@14.1.1-canary.71)(react-dom@18.2.0)(react@18.2.0) postcss: specifier: 8.4.35 version: 8.4.35 @@ -153,11 +153,11 @@ packages: '@jridgewell/trace-mapping': 0.3.22 dev: false - /@auth/core@0.26.3: - resolution: {integrity: sha512-Ka6rMjWMdiQCvLW/CnYZxj4Rq2bhQ/ZtU32NLxmtyAaixGb0mRXQ9MxJUBZA7GHovbghdzu55p2Cb54qNlVFzw==} + /@auth/core@0.27.0: + resolution: {integrity: sha512-3bydnRJIM/Al6mkYmb53MsC+6G8ojw3lLPzwgVnX4dCo6N2lrib6Wq6r0vxZIhuHGjLObqqtUfpeaEj5aeTHFg==} peerDependencies: '@simplewebauthn/browser': ^9.0.1 - '@simplewebauthn/server': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 nodemailer: ^6.8.0 peerDependenciesMeta: '@simplewebauthn/browser': @@ -1563,8 +1563,8 @@ packages: - utf-8-validate dev: false - /@next/env@14.1.1-canary.70: - resolution: {integrity: sha512-y1Ye30DB15DLGM6E/VcOnkWgErtLSkszDks6opBtUnqI9Vr1gXPuIxNpH08our8/VyfyFvG0An5GBbMcooyLSg==} + /@next/env@14.1.1-canary.71: + resolution: {integrity: sha512-3ls1iTTHMZrVtjWmiG5MFQZvvdKY+VEcvyzqVSX03MAU5UmE6G+4oB+lKXIrtApBN91EgRu/mx5sBWmeNQ7DuA==} dev: false /@next/eslint-plugin-next@14.1.0: @@ -1573,8 +1573,8 @@ packages: glob: 10.3.10 dev: false - /@next/swc-darwin-arm64@14.1.1-canary.70: - resolution: {integrity: sha512-eb6RhknFYzamnjHc1diSO/3ymEUMHBJDnrQilTqEjOiOx8oR/GshP3136KDMuF/JlIxqeNTojr2vKMyRNnC7tw==} + /@next/swc-darwin-arm64@14.1.1-canary.71: + resolution: {integrity: sha512-fTbEiTuD9XOstiM4bxxQoz8vzS/Yl2PDWFQQuD1m7H0sf2dj5kW1xmyYB0Sa5n3JEeLSz0415faWoZ3JfWrobg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -1582,8 +1582,8 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@14.1.1-canary.70: - resolution: {integrity: sha512-1Cqt0OmpI3J6Wq5bopzUpjJWoY0W92RcaSJdWSsmXgrLnxBHSmaPPhlDt3ZKZ/0f/9RDYXtqUnwS+q984f1R7w==} + /@next/swc-darwin-x64@14.1.1-canary.71: + resolution: {integrity: sha512-aJgvXTm50TzxdgdWu/Wgm2sgSoZXGyWDGMA+VR6osNrJCBdILvK5bLX/moE8grhKIMnAl+fE4xVvM0q+SgzpVA==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -1591,8 +1591,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@14.1.1-canary.70: - resolution: {integrity: sha512-PGPhSYuVrilIVlPz9Lj3fyLs2nkB+eX2mK0GPpX25yCXFr2UD2vVhiMBqfFpkGtVKLvOjWhzjWQxFxN4u/NtRg==} + /@next/swc-linux-arm64-gnu@14.1.1-canary.71: + resolution: {integrity: sha512-dg0ibSNATNYdRCag2G/qunteDyMQmj00SelTbV3rrnWu+BV+NdqSeKi62N3oEyAznZc7GnNKemwGtin4PFxJkA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1600,8 +1600,8 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@14.1.1-canary.70: - resolution: {integrity: sha512-EcW14+f5/vDa3Zn4Nmw7KqJpmbFObdBYPHxuuti6bKc0VYsWgoPQEyniHKr9EEsI0efrNX05Kzaoy/3T5ZuS7w==} + /@next/swc-linux-arm64-musl@14.1.1-canary.71: + resolution: {integrity: sha512-ECp672RF6DSyufqTuDCrITAfYESN3g22fSxw+C1NQXns0PhUyy3Wuzc6SkGaD27FJmKdV+bFTplaPWykZuZVfg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -1609,8 +1609,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@14.1.1-canary.70: - resolution: {integrity: sha512-aGPexcyfMKCHMQ5AoKehvMETLQcCOjJOcO0GK90fVO51d67DiOQo/v+EUm3M6wuciv6K7VKbqB9rYLPSPY6ZpA==} + /@next/swc-linux-x64-gnu@14.1.1-canary.71: + resolution: {integrity: sha512-GP5pkRVq+3AMBjVvRpvSft/T7psXRC8neOWG1iEOPaQFn/jpRxdo6pSVJ3koc5jcyjhePCcFA09JutuoBBZVxA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1618,8 +1618,8 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@14.1.1-canary.70: - resolution: {integrity: sha512-MI4+TZaNpZ61PwiR4F/pTdO21js+yRvSAXGMstmMF3memZYhFEIRmGMmcO6RewUd843r3TKsROG138AIztQFLA==} + /@next/swc-linux-x64-musl@14.1.1-canary.71: + resolution: {integrity: sha512-8JKHbO3o4qe+HIAgw8rdfxzuGRegeFTeO+i8fG6WjUAfKYydOX3KHnjp12UsoRixrp+pSPRFQjsq8PsSkFArSA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -1627,8 +1627,8 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@14.1.1-canary.70: - resolution: {integrity: sha512-7CgLuiCPndVl8vrKVIS/NKXpuEqN+kdgM9aVrAyIUyAjcltBFKlTgJFAylPUb8ZGPW6URdKk+snJ7adkpsBA4w==} + /@next/swc-win32-arm64-msvc@14.1.1-canary.71: + resolution: {integrity: sha512-77fqJQ3M6N7Ey8iK2jP6xPdgHfscC+T61jgDPBNIHGVWvvZj5Vki4Agxslejto0uqqu59lpkn8yRk9/u2e9FZA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -1636,8 +1636,8 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@14.1.1-canary.70: - resolution: {integrity: sha512-fptIFqxpUntN1HEbkn41ERMN3+uILHS5OzTUbm/ilAARIKc33clZ6VzhoyGCY0VFPF38L7hDUgCOfu/wjmUz8g==} + /@next/swc-win32-ia32-msvc@14.1.1-canary.71: + resolution: {integrity: sha512-i4nQ8zKc9E2pib9TuLS3NKn4nq//zY7iSWPY49y79Y1XR5JkQEy2Sai/kbOY/vbhx86vzyB7aN31RqcdFFNGTg==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -1645,8 +1645,8 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@14.1.1-canary.70: - resolution: {integrity: sha512-0URUGOsTfddsxQORgX4TIRBQUEhlZve8K+XxTEQXj23caUktwQjRVkI7Pah6prPuHTf3OeKhnnfVMLCFyHW8Rw==} + /@next/swc-win32-x64-msvc@14.1.1-canary.71: + resolution: {integrity: sha512-hfrhD5DEYjgdzS+v56j9KOirN0qPTjtSQF5rlJJwwOMfZmFtrAzhD0uhj4KUC+9HMnQpvPRvnm71JgmGzFI1Mw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -3243,7 +3243,7 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: false - /@vercel/analytics@1.2.2(next@14.1.1-canary.70)(react@18.2.0): + /@vercel/analytics@1.2.2(next@14.1.1-canary.71)(react@18.2.0): resolution: {integrity: sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==} peerDependencies: next: '>= 13' @@ -3254,7 +3254,7 @@ packages: react: optional: true dependencies: - next: 14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 server-only: 0.0.1 dev: false @@ -3279,7 +3279,7 @@ packages: ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) dev: false - /@vercel/speed-insights@1.0.10(next@14.1.1-canary.70)(react@18.2.0): + /@vercel/speed-insights@1.0.10(next@14.1.1-canary.71)(react@18.2.0): resolution: {integrity: sha512-4uzdKB0RW6Ff2FkzshzjZ+RlJfLPxgm/00i0XXgxfMPhwnnsk92YgtqsxT9OcPLdJUyVU1DqFlSWWjIQMPkh0g==} requiresBuild: true peerDependencies: @@ -3303,7 +3303,7 @@ packages: vue-router: optional: true dependencies: - next: 14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false @@ -6194,11 +6194,11 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: false - /next-auth@5.0.0-beta.9(next@14.1.1-canary.70)(react@18.2.0): - resolution: {integrity: sha512-BWFiwJ/wzfxWpHnGpAoFsXHSlVofWgFns6tjtIGeDrXfEf3D+afnBpmzCNyek2RNYDVgMHi8Q5uXzFoNBd2l5g==} + /next-auth@5.0.0-beta.13(next@14.1.1-canary.71)(react@18.2.0): + resolution: {integrity: sha512-2m2Gq69WQ0YXcHCCpHn2y5z1bxSlqD/XOuAgrdtz49/VIAdTFFeYZz97RYqf6xMF8VGmoG32VUnJ6LzaHk6Fwg==} peerDependencies: '@simplewebauthn/browser': ^9.0.1 - '@simplewebauthn/server': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 next: ^14 nodemailer: ^6.6.5 react: ^18.2.0 @@ -6210,25 +6210,25 @@ packages: nodemailer: optional: true dependencies: - '@auth/core': 0.26.3 - next: 14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + '@auth/core': 0.27.0 + next: 14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 dev: false - /next-themes@0.2.1(next@14.1.1-canary.70)(react-dom@18.2.0)(react@18.2.0): + /next-themes@0.2.1(next@14.1.1-canary.71)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} peerDependencies: next: '*' react: '*' react-dom: '*' dependencies: - next: 14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /next@14.1.1-canary.70(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-mTi8FgDUuU/pnNUbfEPUG3CtlmQJz+WbHbSuE75DBtxUZe7g4IY92336TiQBaoyNnhRJBCjCILWFFj8XZCEtjQ==} + /next@14.1.1-canary.71(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Es0dlb3GNtOQoTnsgU9tXLQbALDuz9q6JtRp/WCIHJW2T5EBOoJ8Gvh1IDn1eC5vWDpuRpMMdSoimc3/JWzguA==} engines: {node: '>=18.17.0'} hasBin: true peerDependencies: @@ -6242,7 +6242,7 @@ packages: sass: optional: true dependencies: - '@next/env': 14.1.1-canary.70 + '@next/env': 14.1.1-canary.71 '@swc/helpers': 0.5.5 busboy: 1.6.0 caniuse-lite: 1.0.30001585 @@ -6252,15 +6252,15 @@ packages: react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.23.9)(react@18.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 14.1.1-canary.70 - '@next/swc-darwin-x64': 14.1.1-canary.70 - '@next/swc-linux-arm64-gnu': 14.1.1-canary.70 - '@next/swc-linux-arm64-musl': 14.1.1-canary.70 - '@next/swc-linux-x64-gnu': 14.1.1-canary.70 - '@next/swc-linux-x64-musl': 14.1.1-canary.70 - '@next/swc-win32-arm64-msvc': 14.1.1-canary.70 - '@next/swc-win32-ia32-msvc': 14.1.1-canary.70 - '@next/swc-win32-x64-msvc': 14.1.1-canary.70 + '@next/swc-darwin-arm64': 14.1.1-canary.71 + '@next/swc-darwin-x64': 14.1.1-canary.71 + '@next/swc-linux-arm64-gnu': 14.1.1-canary.71 + '@next/swc-linux-arm64-musl': 14.1.1-canary.71 + '@next/swc-linux-x64-gnu': 14.1.1-canary.71 + '@next/swc-linux-x64-musl': 14.1.1-canary.71 + '@next/swc-win32-arm64-msvc': 14.1.1-canary.71 + '@next/swc-win32-ia32-msvc': 14.1.1-canary.71 + '@next/swc-win32-x64-msvc': 14.1.1-canary.71 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros diff --git a/src/components/ImageBlurFallback.tsx b/src/components/ImageBlurFallback.tsx index 1b1162e8..64d1c4ef 100644 --- a/src/components/ImageBlurFallback.tsx +++ b/src/components/ImageBlurFallback.tsx @@ -1,22 +1,87 @@ +'use client'; + +/* eslint-disable jsx-a11y/alt-text */ import { BLUR_ENABLED } from '@/site/config'; import { clsx} from 'clsx/lite'; import Image, { ImageProps } from 'next/image'; +import { useEffect, useRef, useState } from 'react'; export default function ImageBlurFallback(props: ImageProps) { + const { + className, + priority, + blurDataURL, + ...rest + } = props; + + const [wasCached, setWasCached] = useState(true); + const [isLoading, setIsLoading] = useState(true); + const [didError, setDidError] = useState(false); + + const [hideBlurPlaceholder, setHideBlurPlaceholder] = useState(false); + + const imageClassName = 'object-cover h-full'; + + const imgRef = useRef(null); + + useEffect(() => { + const timeout = setTimeout( + () => setWasCached(imgRef.current?.complete ?? false), + 100, + ); + return () => clearTimeout(timeout); + }, []); + + useEffect(() => { + if (!isLoading && !didError) { + const timeout = setTimeout(() => { + setHideBlurPlaceholder(true); + }, 1000); + return () => clearTimeout(timeout); + } + }, [isLoading, didError]); + + const showPlaceholder = + !wasCached && + !hideBlurPlaceholder; + return ( - // eslint-disable-next-line jsx-a11y/alt-text - +
+ {showPlaceholder && +
+ {(BLUR_ENABLED && props.blurDataURL) + ? + :
} +
} + setIsLoading(false), + onError: () => setDidError(true), + }} /> +
); } diff --git a/src/components/ImageSmall.tsx b/src/components/ImageSmall.tsx index 60a9f9ff..d13cb0e7 100644 --- a/src/components/ImageSmall.tsx +++ b/src/components/ImageSmall.tsx @@ -23,7 +23,6 @@ export default function ImageSmall({ alt, priority, blurDataURL: blurData, - placeholder: 'blur', width: IMAGE_SMALL_WIDTH, height: Math.round(IMAGE_SMALL_WIDTH / aspectRatio), }} /> diff --git a/src/components/ImageTiny.tsx b/src/components/ImageTiny.tsx index ac1cbff3..5e976775 100644 --- a/src/components/ImageTiny.tsx +++ b/src/components/ImageTiny.tsx @@ -19,10 +19,7 @@ export default function ImageTiny({ className, src, alt, - ...blurData && { - blurDataURL: blurData, - placeholder: 'blur', - }, + blurDataURL: blurData, width: IMAGE_TINY_WIDTH, height: Math.round(IMAGE_TINY_WIDTH / aspectRatio), }} /> diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index c8b3c5a9..64ed24ec 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -55,12 +55,7 @@ export default function PhotoGrid({
*]:flex [&>*]:w-full [&>*]:h-full', - '[&>*>*]:object-cover [&>*>*]:min-h-full', - ) + ? 'aspect-square overflow-hidden' : undefined} style={{ ...GRID_ASPECT_RATIO !== 0 && { diff --git a/src/photo/PhotoSmall.tsx b/src/photo/PhotoSmall.tsx index 48883fff..c41eda56 100644 --- a/src/photo/PhotoSmall.tsx +++ b/src/photo/PhotoSmall.tsx @@ -5,8 +5,6 @@ import { clsx } from 'clsx/lite'; import { pathForPhoto } from '@/site/paths'; import { Camera } from '@/camera'; import { FilmSimulation } from '@/simulation'; -import AdminPhotoMenu from '@/admin/AdminPhotoMenu'; -import { Suspense } from 'react'; export default function PhotoSmall({ photo, @@ -14,7 +12,6 @@ export default function PhotoSmall({ camera, simulation, selected, - showAdminMenu, priority, }: { photo: Photo @@ -22,28 +19,17 @@ export default function PhotoSmall({ camera?: Camera simulation?: FilmSimulation selected?: boolean - showAdminMenu?: boolean priority?: boolean }) { return ( - - {showAdminMenu && - } -