diff options
Diffstat (limited to '')
-rw-r--r-- | frontend/src/lib/gallery/GalleryPage.svelte | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/frontend/src/lib/gallery/GalleryPage.svelte b/frontend/src/lib/gallery/GalleryPage.svelte new file mode 100644 index 0000000..449321c --- /dev/null +++ b/frontend/src/lib/gallery/GalleryPage.svelte @@ -0,0 +1,93 @@ +<script lang="ts"> + import type { PageFragment } from '$gql/graphql'; + import { getSelectionContext } from '$lib/Selection'; + import SelectionOverlay from '$lib/selection/SelectionOverlay.svelte'; + import { src } from '$lib/Utils'; + import { createEventDispatcher } from 'svelte'; + + export let page: PageFragment; + export let index: number; + + const selection = getSelectionContext<PageFragment>(); + + let span: 'single' | 'double' | 'triple'; + + $: page.image.aspectRatio, updateSpan(); + + function updateSpan() { + const aspectRatio = page.image.aspectRatio; + + if (aspectRatio <= 1) { + span = 'single'; + } else if (aspectRatio > 1 && aspectRatio <= 2) { + span = 'double'; + } else if (aspectRatio > 2) { + span = 'triple'; + } + } + + const dispatch = createEventDispatcher<{ open: number; cover: number }>(); + + function press(event: MouseEvent | KeyboardEvent) { + if (event instanceof KeyboardEvent && event.key !== 'Enter') { + return; + } + + if ($selection.active) { + if (event.ctrlKey) { + dispatch('open', index); + } else if (selectable) { + $selection = $selection.update(index, event.shiftKey); + } + } else if (event.ctrlKey) { + dispatch('cover', page.id); + } else { + dispatch('open', index); + } + + event.preventDefault(); + } + + $: selectable = $selection.selectable(page); + $: dim = $selection.active && !selectable; + $: selected = $selection.contains(page.id); +</script> + +<div + class:dim + role="button" + tabindex="0" + class="{span} relative overflow-hidden rounded" + on:click={press} + on:keydown={press} +> + <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> |