11'use client' ;
22import { tcls } from '@/lib/tailwind' ;
3- import { useRef } from 'react' ;
4- import { useResizeObserver } from 'usehooks-ts' ;
53import type { ImageSize } from '../utils' ;
4+ import { useCoverPosition } from './useCoverPosition' ;
65
76interface ImageAttributes {
87 src : string ;
@@ -20,29 +19,27 @@ interface Images {
2019
2120const PAGE_COVER_SIZE : ImageSize = { width : 1990 , height : 480 } ;
2221
23- function getTop ( container : { height ?: number ; width ?: number } , y : number , img : ImageAttributes ) {
24- // When the size of the image hasn't been determined, we fallback to the center position
25- if ( ! img . size || y === 0 ) return '50%' ;
26- const ratio =
27- container . height && container . width
28- ? Math . max ( container . width / img . size . width , container . height / img . size . height )
29- : 1 ;
30- const scaledHeight = img . size ? img . size . height * ratio : PAGE_COVER_SIZE . height ;
31- const top =
32- container . height && img . size ? ( container . height - scaledHeight ) / 2 + y * ratio : y ;
33- return `${ top } px` ;
22+ interface PageCoverImageProps {
23+ imgs : Images ;
24+ y : number ;
25+ // Only if the `height` was customized by the user (and thus defined), we use it to set the cover's height and skip the default behaviour of fixed aspect-ratio.
26+ height : number | undefined ;
3427}
3528
36- export function PageCoverImage ( { imgs, y } : { imgs : Images ; y : number } ) {
37- const containerRef = useRef < HTMLDivElement > ( null ) ;
29+ export function PageCoverImage ( props : PageCoverImageProps ) {
30+ const { imgs, y, height } = props ;
31+ const { containerRef, objectPositionY, isLoading } = useCoverPosition ( imgs , y ) ;
3832
39- const container = useResizeObserver ( {
40- // @ts -expect-error wrong types
41- ref : containerRef ,
42- } ) ;
33+ if ( isLoading ) {
34+ return (
35+ < div className = "h-full w-full overflow-hidden" ref = { containerRef } >
36+ < div className = "h-full w-full animate-pulse bg-gradient-to-br from-gray-100 to-gray-200 dark:from-gray-800 dark:to-gray-900" />
37+ </ div >
38+ ) ;
39+ }
4340
4441 return (
45- < div className = "h-full w-full overflow-hidden" ref = { containerRef } >
42+ < div className = "h-full w-full overflow-hidden" ref = { containerRef } style = { { height } } >
4643 < img
4744 src = { imgs . light . src }
4845 srcSet = { imgs . light . srcSet }
@@ -51,8 +48,11 @@ export function PageCoverImage({ imgs, y }: { imgs: Images; y: number }) {
5148 alt = "Page cover"
5249 className = { tcls ( 'w-full' , 'object-cover' , imgs . dark ? 'dark:hidden' : '' ) }
5350 style = { {
54- aspectRatio : `${ PAGE_COVER_SIZE . width } /${ PAGE_COVER_SIZE . height } ` ,
55- objectPosition : `50% ${ getTop ( container , y , imgs . light ) } ` ,
51+ aspectRatio : height
52+ ? undefined
53+ : `${ PAGE_COVER_SIZE . width } /${ PAGE_COVER_SIZE . height } ` ,
54+ objectPosition : `50% ${ objectPositionY } %` ,
55+ height, // if no height is passed, no height will be set.
5656 } }
5757 />
5858 { imgs . dark && (
@@ -64,8 +64,11 @@ export function PageCoverImage({ imgs, y }: { imgs: Images; y: number }) {
6464 alt = "Page cover"
6565 className = { tcls ( 'w-full' , 'object-cover' , 'dark:inline' , 'hidden' ) }
6666 style = { {
67- aspectRatio : `${ PAGE_COVER_SIZE . width } /${ PAGE_COVER_SIZE . height } ` ,
68- objectPosition : `50% ${ getTop ( container , y , imgs . dark ) } ` ,
67+ aspectRatio : height
68+ ? undefined
69+ : `${ PAGE_COVER_SIZE . width } /${ PAGE_COVER_SIZE . height } ` ,
70+ objectPosition : `50% ${ objectPositionY } %` ,
71+ height, // if no height is passed, no height will be set.
6972 } }
7073 />
7174 ) }
0 commit comments