feat(calendar): image/attachment per event, direct links, copy link, ImageModal component
- calendar_item schema: flyer → image (type: image), attachment (assetUrl)
- CalendarItemData: image + attachment fields
- event anchor IDs (#event-{slug}) with onMount hash scroll + auto-open
- share button uses direct calendar anchor URL
- copy link button (mdi:link-variant) copies anchor URL to clipboard
- ImageModal extracted as reusable component
- action buttons always show text (no expand-on-hover)
- onDestroy window guard (SSR fix)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
import Icon from "@iconify/svelte";
|
||||
import "$lib/iconify-offline";
|
||||
|
||||
let {
|
||||
src,
|
||||
alt = "",
|
||||
onclose,
|
||||
}: { src: string; alt?: string; onclose: () => void } = $props();
|
||||
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
if (e.key === "Escape") onclose();
|
||||
}
|
||||
|
||||
onMount(() => window.addEventListener("keydown", onKeydown));
|
||||
onDestroy(() => {
|
||||
if (typeof window !== "undefined")
|
||||
window.removeEventListener("keydown", onKeydown);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 p-4 cursor-zoom-out"
|
||||
onclick={onclose}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label={alt || "Bild Vollansicht"}
|
||||
>
|
||||
<img
|
||||
{src}
|
||||
{alt}
|
||||
class="max-w-full max-h-full object-contain rounded shadow-2xl cursor-default"
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onclick={onclose}
|
||||
class="absolute top-4 right-4 p-2 rounded-full bg-black/50 text-white hover:bg-black/70 transition-colors"
|
||||
aria-label="Schließen"
|
||||
>
|
||||
<Icon icon="mdi:close" class="size-5" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
Reference in New Issue
Block a user