2024-07-13 13:56:16 +02:00

210 lines
5.2 KiB
Plaintext

---
import Credits from "./Credits.astro";
import DownloadButton from "./DownloadButton.astro";
import AppLayoutTitle from "./AppLayout/components/AppLayoutTitle.astro";
import type { ComponentProps } from "astro/types";
import Attributes from "./Attributes.astro";
import { sizesToSrcset } from "src/utils/img";
import { Icon } from "astro-icon/components";
import RichText from "./RichText/RichText.astro";
import type {
EndpointImage,
EndpointScanImage,
EndpointPayloadImage,
EndpointCredit,
} from "src/shared/payload/endpoint-types";
import type { RichTextContent } from "src/shared/payload/rich-text";
interface Props {
previousImageHref?: string | undefined;
nextImageHref?: string | undefined;
image: EndpointImage | EndpointScanImage | EndpointPayloadImage;
pretitle?: string | undefined;
title: string;
subtitle?: string | undefined;
description?: RichTextContent | undefined;
lang?: string | undefined;
attributes?: ComponentProps<typeof Attributes>["attributes"] | undefined;
metaAttributes?: ComponentProps<typeof Attributes>["attributes"] | undefined;
credits?: EndpointCredit[] | undefined;
filename?: string | undefined;
smallTitle?: boolean | undefined;
}
const {
nextImageHref,
previousImageHref,
image: { url, width, height, sizes },
attributes = [],
metaAttributes = [],
credits = [],
description,
lang,
pretitle,
title,
subtitle,
filename,
smallTitle = false,
} = Astro.props;
const hasNavigation = previousImageHref || nextImageHref;
---
{/* ------------------------------------------- HTML ------------------------------------------- */}
<div id="container">
<div id="image-viewer" class:list={{ "with-buttons": hasNavigation }}>
{
hasNavigation && (
<a
id="previous-button"
class:list={{ hidden: !previousImageHref, pressable: true }}
href={previousImageHref}>
<Icon name="material-symbols:chevron-left" />
</a>
)
}
<a id="image-anchor" href={url} target="_blank" style=`aspect-ratio:${width}/${height};`>
<img
src={url}
srcset={sizesToSrcset(sizes)}
sizes={`(max-aspect-ratio: ${width / 0.9}/${height / 0.7}) 90vw, ${(width / height) * 70}vh`}
width={width}
height={height}
/>
</a>
{
hasNavigation && (
<a
id="next-button"
class:list={{ hidden: !nextImageHref, pressable: true }}
href={nextImageHref}>
<Icon name="material-symbols:chevron-right" />
</a>
)
}
</div>
<div
id="info"
class:list={{
complex:
attributes.length > 0 || metaAttributes.length > 0 || credits.length > 0 || description,
}}>
<div>
{
smallTitle ? (
<h1 class="font-4xl" lang={lang}>
{title}
</h1>
) : (
<AppLayoutTitle pretitle={pretitle} title={title} subtitle={subtitle} lang={lang} />
)
}
{description && <RichText content={description} context={{ lang }} />}
</div>
{attributes.length > 0 && <Attributes attributes={attributes} />}
{credits.length > 0 && <Credits credits={credits} />}
{metaAttributes.length > 0 && <Attributes attributes={metaAttributes} />}
{filename && <DownloadButton href={url} filename={filename} useBlob />}
</div>
</div>
{/* ------------------------------------------- CSS -------------------------------------------- */}
<style>
#container {
display: flex;
flex-direction: column;
gap: 3em;
align-items: center;
margin-top: 3em;
& > #image-viewer {
&.with-buttons {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 1em;
place-items: center;
}
& > a.hidden {
visibility: hidden;
}
& > a {
&.pressable {
border-radius: 9999px;
padding-left: 1em;
padding-right: 1em;
height: 2.5em;
display: flex;
place-items: center;
place-content: center;
& > svg {
width: 1.5em;
height: 1.5em;
}
}
}
& > #image-anchor {
transition: 100ms scale;
box-shadow: 0 5px 20px -10px var(--color-shadow-0);
&:hover,
&:focus-visible {
scale: 102%;
}
max-height: 70vh;
}
}
& > #info {
display: flex;
flex-direction: column;
gap: 4em;
align-items: start;
@media (max-width: 35rem) {
gap: 6em;
}
&:not(.complex) {
align-items: center;
gap: 2em;
}
& > div {
display: flex;
flex-direction: column;
gap: 32px;
}
}
}
h1 {
max-width: 35em;
}
</style>
{/* ------------------------------------------- JS --------------------------------------------- */}
<script>
document.addEventListener("keydown", async (e) => {
const previousButton = document.getElementById("previous-button");
const nextButton = document.getElementById("next-button");
if (previousButton && e.key === "ArrowLeft") {
previousButton.click();
} else if (nextButton && e.key === "ArrowRight") {
nextButton.click();
}
});
</script>