Files
EventSnap/frontend/src/lib/diashow/transitions/kenburns.svelte
fabi 91ff961850 fix(security): medium/low — event-lock, atomic config, a11y, diashow, hygiene
- social: likes/comments rejected on a closed event (e2e proven).
- admin: patch_config validates-then-writes atomically; char-based length.
- hashtag/comment models: atomic tag writes in edit + comment paths.
- Modal: inert the background (modal-inert action) for screen readers.
- sse.ts: idempotent visibilitychange listener (no duplicate reconnects).
- diashow: videos advance on `ended` (transitions + page wiring).
- docs/hygiene: README clone-case fix; removed stale committed .env.test and
  gitignored it; docker-compose.dev.yml tidy.

Left documented as accepted-risk per plan: PIN-persist-after-logout,
UUID-reachable hidden uploads, DECISION-media-auth.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:25:58 +02:00

55 lines
1.4 KiB
Svelte

<script lang="ts">
// Crossfade + slow zoom and pan (the "Ken Burns" effect). Image-only — videos
// fall back to the crossfade behaviour to avoid double-animation.
interface Props {
src: string;
isVideo: boolean;
durationMs: number;
/** Fired when a video slide finishes so the parent can advance early. */
onended?: () => void;
}
let { src, isVideo, durationMs, onended }: Props = $props();
// Mild random pan so each slide feels different. Range chosen so the image never
// pans out of frame given the object-fit: cover.
const panX = Math.round((Math.random() - 0.5) * 6); // -3% .. +3%
const panY = Math.round((Math.random() - 0.5) * 6);
</script>
<div
class="absolute inset-0 flex items-center justify-center overflow-hidden bg-black"
style="animation: kb-fade {durationMs}ms ease-out forwards;"
>
{#if isVideo}
<!-- svelte-ignore a11y_media_has_caption -->
<video
{src}
autoplay
muted
playsinline
{onended}
class="h-full w-full object-contain"
></video>
{:else}
<img
{src}
alt=""
class="h-full w-full object-cover"
style="animation: kb-zoom 10s ease-out forwards; transform-origin: {50 + panX}% {50 + panY}%;"
/>
{/if}
</div>
<style>
@keyframes kb-fade {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes kb-zoom {
from { transform: scale(1.0); }
to { transform: scale(1.1); }
}
</style>