diff --git a/svelte-app/src/components/document/content/header.svelte b/svelte-app/src/components/document/content/header.svelte index b302ea57d..e4324f9d0 100644 --- a/svelte-app/src/components/document/content/header.svelte +++ b/svelte-app/src/components/document/content/header.svelte @@ -8,12 +8,14 @@ import ArrowButton from '$components/controls/arrow-button.svelte'; import Divider from '$components/divider.svelte'; import Icon from '$components/icon.svelte'; + import Image from '$components/images/image.svelte'; import Link from '$components/link.svelte'; import ImageCarousel from '$components/portable-text/image-carousel.svelte'; - import type { PostDocument, ProjectDocument, ProjectImage } from '$types'; + import type { PostDocument, ProjectDocument, ProjectImage, RouteFetch } from '$types'; export let data: PostDocument | ProjectDocument, + routeFetch: RouteFetch, images: ProjectImage[] | undefined = undefined, model = data._type; @@ -90,7 +92,17 @@ {#if data._type === 'project' && images?.length} - + {#if images.length > 1} + + {:else} + + {/if} {/if} diff --git a/svelte-app/src/components/images/image-modal.svelte b/svelte-app/src/components/images/image-modal.svelte new file mode 100644 index 000000000..0181d4b39 --- /dev/null +++ b/svelte-app/src/components/images/image-modal.svelte @@ -0,0 +1,51 @@ + + + { + if (show) { + switch (e.key) { + case 'Escape': + show = false; + break; + case 'Tab': + e.preventDefault(); + dialog.focus(); + break; + } + } + }} +/> + +{#if show} + + (show = false)} + on:keydown={(e) => { + if (e.key === 'Escape') { + show = false; + } + }} + in:fade={{ duration: BASE_ANIMATION_DURATION }} + out:fade={{ duration: BASE_ANIMATION_DURATION }} + > +
+
+{/if} + + diff --git a/svelte-app/src/components/images/image.svelte b/svelte-app/src/components/images/image.svelte new file mode 100644 index 000000000..dac6aa6f6 --- /dev/null +++ b/svelte-app/src/components/images/image.svelte @@ -0,0 +1,173 @@ + + +
+ {#await srcPromise || new Promise((_res) => {})} +
+ + + {:then src} + + {:catch e} +

Error: {e?.message || e}

+ {_key} + {/await} + +
+ + + {_key} + + + diff --git a/svelte-app/src/components/portable-text/image-carousel.svelte b/svelte-app/src/components/portable-text/image-carousel.svelte index 966631084..43c146166 100644 --- a/svelte-app/src/components/portable-text/image-carousel.svelte +++ b/svelte-app/src/components/portable-text/image-carousel.svelte @@ -1,9 +1,10 @@ -
- {#await srcPromise} -
- - - {:then src} - {_key} - {:catch e} -

Error: {e?.message || e}

- {_key} - {/await} -
- - + diff --git a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts index 9a496e221..f3d3d00fa 100644 --- a/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts +++ b/svelte-app/src/routes/[[lang=lang]]/work/[slug]/+page.ts @@ -12,7 +12,7 @@ const urlToBase64Asset = async (url: string, fetch: typeof window.fetch) => { if (!response.ok) { Logger.error(`Failed to fetch image ${url}`); - return undefined; + return ''; } const arrayBuffer = await response.arrayBuffer(), @@ -62,7 +62,8 @@ export const load = (async ({ fetch, params, url }) => { return { crop, placeholder: await urlToBase64Asset(placeholder, fetch), - asset: urlToBase64Asset(url, fetch) + asset: urlToBase64Asset(url, fetch), + sanityAsset: imageAsset } satisfies ProjectImage; })() ); diff --git a/svelte-app/types/app/documents/index.ts b/svelte-app/types/app/documents/index.ts index c06e6fa29..2c8830300 100644 --- a/svelte-app/types/app/documents/index.ts +++ b/svelte-app/types/app/documents/index.ts @@ -1,4 +1,9 @@ -import type { PTBlock, SanityAsset } from '$types/sanity'; +import type { + PTBlock, + SanityAsset, + SanityImageCrop, + SanityImageObject +} from '$types/sanity'; export interface Document extends SanityAsset { slug: Pick & { @@ -29,16 +34,13 @@ export interface DocumentHeadings { } export type ProjectImage = { - crop: { - top: number; - right: number; - bottom: number; - left: number; + crop: SanityImageCrop & { width: number; height: number; }; placeholder?: string; - asset: Promise; + asset: Promise; + sanityAsset: SanityImageObject; }; export type { AuthorDocument, AuthorTimelineItem } from '$types/documents/author'; diff --git a/svelte-app/types/app/sanity/index.ts b/svelte-app/types/app/sanity/index.ts index 16db07334..554febbd5 100644 --- a/svelte-app/types/app/sanity/index.ts +++ b/svelte-app/types/app/sanity/index.ts @@ -16,9 +16,10 @@ export interface SanityReference { _ref: string; _type: string; } -export interface SanityImageObject extends Pick { +export interface SanityImageObject extends Pick { + _key?: string; asset: SanityReference; - crop?: SanityImageCrop; + crop: SanityImageCrop; hotspot?: SanityImageHotspot; } export interface SanityImageCrop {