138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import { Photo, photoHasCameraData, photoHasExifData, titleForPhoto } from '.';
|
|
import SiteGrid from '@/components/SiteGrid';
|
|
import ImageLarge from '@/components/ImageLarge';
|
|
import { cc } from '@/utility/css';
|
|
import Link from 'next/link';
|
|
import { pathForPhoto, pathForPhotoShare } from '@/site/paths';
|
|
import PhotoTags from '@/tag/PhotoTags';
|
|
import ShareButton from '@/components/ShareButton';
|
|
import PhotoCamera from '../camera/PhotoCamera';
|
|
import { Camera, cameraFromPhoto } from '@/camera';
|
|
import PhotoFujifilmSimulation from
|
|
'@/vendors/fujifilm/PhotoFujifilmSimulation';
|
|
|
|
export default function PhotoLarge({
|
|
photo,
|
|
tag,
|
|
priority,
|
|
prefetchShare,
|
|
shouldScrollOnShare,
|
|
showCamera = true,
|
|
shareCamera,
|
|
}: {
|
|
photo: Photo
|
|
tag?: string
|
|
camera?: Camera
|
|
priority?: boolean
|
|
prefetchShare?: boolean
|
|
shouldScrollOnShare?: boolean
|
|
showCamera?: boolean
|
|
shareCamera?: boolean
|
|
}) {
|
|
const tagsToShow = photo.tags.filter(t => t !== tag);
|
|
|
|
const camera = cameraFromPhoto(photo);
|
|
|
|
const renderMiniGrid = (children: JSX.Element, rightPadding = true) =>
|
|
<div className={cc(
|
|
'flex gap-y-4',
|
|
'flex-col sm:flex-row md:flex-col',
|
|
'[&>*]:sm:flex-grow',
|
|
rightPadding && 'pr-2',
|
|
)}>
|
|
{children}
|
|
</div>;
|
|
|
|
return (
|
|
<SiteGrid
|
|
contentMain={
|
|
<ImageLarge
|
|
className="w-full"
|
|
alt={titleForPhoto(photo)}
|
|
href={pathForPhoto(photo, tag)}
|
|
src={photo.url}
|
|
aspectRatio={photo.aspectRatio}
|
|
blurData={photo.blurData}
|
|
priority={priority}
|
|
/>}
|
|
contentSide={
|
|
<div className={cc(
|
|
'sticky top-4 self-start',
|
|
'grid grid-cols-2 md:grid-cols-1',
|
|
'gap-y-4',
|
|
'-translate-y-1',
|
|
'mb-4',
|
|
)}>
|
|
{renderMiniGrid(<>
|
|
<div>
|
|
<Link
|
|
href={pathForPhoto(photo)}
|
|
className="font-bold uppercase"
|
|
>
|
|
{titleForPhoto(photo)}
|
|
</Link>
|
|
{tagsToShow.length > 0 &&
|
|
<PhotoTags tags={tagsToShow} />}
|
|
</div>
|
|
{showCamera && photoHasCameraData(photo) &&
|
|
<div className="space-y-0.5">
|
|
<PhotoCamera
|
|
camera={camera}
|
|
showIcon={false}
|
|
hideApple={false}
|
|
/>
|
|
{photo.filmSimulation &&
|
|
<div className="-translate-x-0.5">
|
|
<PhotoFujifilmSimulation
|
|
simulation={photo.filmSimulation}
|
|
/>
|
|
</div>}
|
|
</div>}
|
|
</>)}
|
|
{renderMiniGrid(<>
|
|
{photoHasExifData(photo) &&
|
|
<ul className="text-medium">
|
|
<li>
|
|
{photo.focalLengthFormatted}
|
|
{photo.focalLengthIn35MmFormatFormatted &&
|
|
<>
|
|
{' '}
|
|
<span
|
|
title="35mm equivalent"
|
|
className="text-extra-dim"
|
|
>
|
|
{photo.focalLengthIn35MmFormatFormatted}
|
|
</span>
|
|
</>}
|
|
</li>
|
|
<li>{photo.fNumberFormatted}</li>
|
|
<li>{photo.exposureTimeFormatted}</li>
|
|
<li>{photo.isoFormatted}</li>
|
|
<li>{photo.exposureCompensationFormatted ?? '—'}</li>
|
|
</ul>}
|
|
<div className={cc(
|
|
'flex gap-y-4',
|
|
'flex-col sm:flex-row md:flex-col',
|
|
)}>
|
|
<div className={cc(
|
|
'grow uppercase',
|
|
'text-medium',
|
|
)}>
|
|
{photo.takenAtNaiveFormatted}
|
|
</div>
|
|
<ShareButton
|
|
path={pathForPhotoShare(
|
|
photo,
|
|
tag,
|
|
shareCamera ? camera : undefined,
|
|
)}
|
|
prefetch={prefetchShare}
|
|
shouldScroll={shouldScrollOnShare}
|
|
/>
|
|
</div>
|
|
</>, false)}
|
|
</div>}
|
|
/>
|
|
);
|
|
};
|