79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import type { ReactNode } from 'react';
|
|
|
|
import { ResolvedAssetImage } from './ResolvedAssetImage';
|
|
import type { CustomWorldCoverRenderMode } from '../services/customWorldCover';
|
|
|
|
const COVER_PORTRAIT_CLASS_NAMES = [
|
|
'h-[54%] w-[24%] translate-y-[8%]',
|
|
'h-[68%] w-[30%]',
|
|
'h-[56%] w-[24%] translate-y-[10%]',
|
|
] as const;
|
|
|
|
type CustomWorldCoverArtworkProps = {
|
|
imageSrc?: string | null;
|
|
title: string;
|
|
fallbackLabel: string;
|
|
renderMode?: CustomWorldCoverRenderMode;
|
|
characterImageSrcs?: string[];
|
|
className?: string;
|
|
overlay?: ReactNode;
|
|
};
|
|
|
|
export function CustomWorldCoverArtwork({
|
|
imageSrc,
|
|
title,
|
|
fallbackLabel,
|
|
renderMode = 'image',
|
|
characterImageSrcs = [],
|
|
className = '',
|
|
overlay,
|
|
}: CustomWorldCoverArtworkProps) {
|
|
const coverCharacterImageSrcs = characterImageSrcs.slice(0, 3);
|
|
|
|
return (
|
|
<div
|
|
className={`relative overflow-hidden bg-[radial-gradient(circle_at_top,rgba(255,244,214,0.3),transparent_38%),linear-gradient(180deg,rgba(34,40,55,0.92),rgba(10,12,18,0.96))] ${className}`}
|
|
>
|
|
{imageSrc ? (
|
|
<ResolvedAssetImage
|
|
src={imageSrc}
|
|
alt={title}
|
|
loading="lazy"
|
|
className="absolute inset-0 h-full w-full object-cover"
|
|
/>
|
|
) : null}
|
|
<div className="absolute inset-0 bg-[linear-gradient(180deg,rgba(8,10,14,0.04),rgba(8,10,14,0.26)_46%,rgba(8,10,14,0.82)_100%)]" />
|
|
{!imageSrc ? (
|
|
<div className="absolute inset-0 flex items-center justify-center px-4 text-center text-sm font-semibold tracking-[0.18em] text-zinc-300">
|
|
{fallbackLabel}
|
|
</div>
|
|
) : null}
|
|
{renderMode === 'scene_with_roles' && coverCharacterImageSrcs.length > 0 ? (
|
|
<>
|
|
<div className="absolute inset-x-0 bottom-0 h-[42%] bg-[linear-gradient(180deg,rgba(8,10,14,0)_0%,rgba(8,10,14,0.88)_100%)]" />
|
|
<div className="pointer-events-none absolute inset-x-0 bottom-0 flex items-end justify-center gap-2 px-3 pb-2 sm:pb-3">
|
|
{coverCharacterImageSrcs.map((characterImageSrc, index) => (
|
|
<div
|
|
key={`${title}-cover-character-${index}-${characterImageSrc}`}
|
|
className={`overflow-hidden rounded-[1rem] border border-white/16 bg-[linear-gradient(180deg,rgba(255,255,255,0.14),rgba(255,255,255,0.04))] shadow-[0_12px_28px_rgba(0,0,0,0.4)] ${COVER_PORTRAIT_CLASS_NAMES[index] ?? COVER_PORTRAIT_CLASS_NAMES[1]}`}
|
|
>
|
|
<ResolvedAssetImage
|
|
src={characterImageSrc}
|
|
alt=""
|
|
loading="lazy"
|
|
className="h-full w-full object-cover object-top"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</>
|
|
) : null}
|
|
{overlay ? (
|
|
<div className="pointer-events-none absolute inset-0">{overlay}</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default CustomWorldCoverArtwork;
|