<script lang="ts"> import type { PageFragment } from '$gql/graphql'; import { getSelectionContext } from '$lib/selection/Selection.svelte'; import SelectionOverlay from '$lib/selection/SelectionOverlay.svelte'; import { src } from '$lib/Utils'; interface Props { page: PageFragment; index: number; open: (page: number) => void; updateCover: (page: number) => void; } let { page, index, open, updateCover }: Props = $props(); const selection = getSelectionContext<PageFragment>(); let span: 'single' | 'double' | 'triple' = $derived.by(() => { const aspectRatio = page.image.aspectRatio; if (aspectRatio <= 1) { return 'single'; } else if (aspectRatio > 1 && aspectRatio <= 2) { return 'double'; } else { return 'triple'; } }); function onclick(event: MouseEvent | KeyboardEvent) { if (event instanceof KeyboardEvent && event.key !== 'Enter') { return; } if (selection.active) { if (event.ctrlKey) { open(index); } else if (selectable) { selection.update(index, event.shiftKey); } } else if (event.ctrlKey) { updateCover(page.id); } else { open(index); } event.preventDefault(); } let selectable = $derived(selection.selectable(page)); let dim = $derived(selection.active && !selectable); let selected = $derived(selection.contains(page.id)); </script> <div class:dim role="button" tabindex="0" class="{span} relative overflow-hidden rounded-sm focus-visible:outline-4 focus-visible:outline-blue-600" {onclick} onkeydown={onclick} > <SelectionOverlay position="top" {selected} /> <img class="h-full w-full object-cover object-[center_top] transition-opacity" loading="lazy" alt="" width={page.image.width} height={page.image.height} src={src(page.image)} title={`${page.path} (${page.image.width} x ${page.image.height})`} /> </div> <style> .dim { cursor: not-allowed; } .dim > img { opacity: 0.2; filter: grayscale(1); } .double { grid-column: span 2; } .triple { grid-column: span 3; } </style>