remove PhotoCarousel
This commit is contained in:
parent
3f4d3ef9cf
commit
8b2a6d7234
7 changed files with 0 additions and 604 deletions
|
|
@ -105,7 +105,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
"@splidejs/svelte-splide": "^0.2.9",
|
|
||||||
"@sveltejs/kit": "^2.20.7",
|
"@sveltejs/kit": "^2.20.7",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"journalize": "^2.6.0",
|
"journalize": "^2.6.0",
|
||||||
|
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import { Meta, Canvas } from '@storybook/blocks';
|
|
||||||
|
|
||||||
import * as PhotoCarouselStories from './PhotoCarousel.stories.svelte';
|
|
||||||
|
|
||||||
<Meta of={PhotoCarouselStories} />
|
|
||||||
|
|
||||||
# PhotoCarousel
|
|
||||||
|
|
||||||
The `PhotoCarousel` component creates a simple and accessible photo carousel with built-in lazy-loading and mobile swipe.
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<script>
|
|
||||||
import { PhotoCarousel } from '@reuters-graphics/graphics-components';
|
|
||||||
|
|
||||||
const photos = [
|
|
||||||
{
|
|
||||||
src: 'https://.../myImage.jpg',
|
|
||||||
altText: 'A picture of...',
|
|
||||||
caption: 'My caption...', // Optional
|
|
||||||
credit: 'REUTERS/Jane Doe', // Optional
|
|
||||||
objectFit: 'contain', // Optional
|
|
||||||
objectPosition: '50% 50%', // Optional
|
|
||||||
},
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<PhotoCarousel {photos} />
|
|
||||||
```
|
|
||||||
|
|
||||||
<Canvas of={PhotoCarouselStories.Demo} />
|
|
||||||
|
|
||||||
## Using with ArchieML docs
|
|
||||||
|
|
||||||
With the Graphics Kit, you'll likely get your text value from an ArchieML doc...
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# ArchieML doc
|
|
||||||
[blocks]
|
|
||||||
type: photo-carousel
|
|
||||||
|
|
||||||
# List of photo data
|
|
||||||
[.images]
|
|
||||||
# Photo 1
|
|
||||||
src: 'images/myImage.jpg', # The source path can be a URL or a local path
|
|
||||||
altText: 'A picture of...',
|
|
||||||
caption: 'My caption...', // Optional
|
|
||||||
credit: 'REUTERS/Jane Doe', // Optional
|
|
||||||
objectFit: 'contain', // Optional
|
|
||||||
objectPosition: '50% 50%', // Optional
|
|
||||||
|
|
||||||
# Photo 2
|
|
||||||
src: 'images/myImage2.jpg',
|
|
||||||
altText: 'A picture of...',
|
|
||||||
caption: 'My caption...', // Optional
|
|
||||||
credit: 'REUTERS/Jane Doe', // Optional
|
|
||||||
objectFit: 'contain', // Optional
|
|
||||||
objectPosition: '50% 50%', // Optional
|
|
||||||
...
|
|
||||||
[]
|
|
||||||
[]
|
|
||||||
```
|
|
||||||
|
|
||||||
... which you'll parse out of a ArchieML block object before passing to the `PhotoCarousel` component.
|
|
||||||
|
|
||||||
> **Note:** If you're using local images files stored in your Graphics Kit project, prefix `assets` to the image source path, as in the example below.
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<!-- App.svelte -->
|
|
||||||
<script>
|
|
||||||
import { PhotoCarousel } from '@reuters-graphics/graphics-components';
|
|
||||||
import { assets } from '$app/paths'; // 👈 If using in the Graphics Kit...
|
|
||||||
|
|
||||||
import content from '$locales/en/content.json';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#each content.blocks as block}
|
|
||||||
{#if block.type === 'photo-carousel'}
|
|
||||||
<PhotoCarousel
|
|
||||||
images={block.images.map((img) => ({
|
|
||||||
...img,
|
|
||||||
src: `${assets}/${img.src}`,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
```
|
|
||||||
|
|
||||||
<Canvas of={PhotoCarouselStories.Demo} />
|
|
||||||
|
|
||||||
## Custom text
|
|
||||||
|
|
||||||
To customise the credit and/or caption style, use the `credit` and `caption` [snippets](https://svelte.dev/docs/svelte/snippet) and pass `photo` as an argument.
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<PhotoCarousel {images}>
|
|
||||||
<!-- Pass `image` and use the `image.credit` string in the HTML -->
|
|
||||||
{#snippet credit(image)}
|
|
||||||
<p class="custom-credit">{image.credit}</p>
|
|
||||||
{/snippet}
|
|
||||||
|
|
||||||
<!-- Pass `image` and use the `image.caption` string in the HTML -->
|
|
||||||
{#snippet caption(image)}
|
|
||||||
<p class="custom-caption">{image.caption}</p>
|
|
||||||
{/snippet}
|
|
||||||
</PhotoCarousel>
|
|
||||||
|
|
||||||
<!-- Customise credit and caption styles -->
|
|
||||||
<style lang="scss">
|
|
||||||
p {
|
|
||||||
position: absolute;
|
|
||||||
color: white;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
padding: 0 5px;
|
|
||||||
&.custom-credit {
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
&.custom-caption {
|
|
||||||
bottom: 5px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
<Canvas of={PhotoCarouselStories.CustomText} />
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
<script module lang="ts">
|
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
||||||
import PhotoCarousel from './PhotoCarousel.svelte';
|
|
||||||
|
|
||||||
const { Story } = defineMeta({
|
|
||||||
title: 'Components/Multimedia/PhotoCarousel',
|
|
||||||
component: PhotoCarousel,
|
|
||||||
argTypes: {
|
|
||||||
width: {
|
|
||||||
control: 'select',
|
|
||||||
options: ['normal', 'wide', 'wider', 'widest', 'fluid'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import imagesJson from './demo/images.json';
|
|
||||||
|
|
||||||
const images = imagesJson.map((img) => ({ ...img, altText: img.caption }));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Story
|
|
||||||
name="Demo"
|
|
||||||
args={{
|
|
||||||
images,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Story name="Custom text" exportName="CustomText">
|
|
||||||
<PhotoCarousel {images}>
|
|
||||||
{#snippet credit(image)}
|
|
||||||
<p class="custom-credit">{image.credit}</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet caption(image)}
|
|
||||||
<p class="custom-caption">{image.caption}</p>
|
|
||||||
{/snippet}
|
|
||||||
</PhotoCarousel>
|
|
||||||
</Story>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
p {
|
|
||||||
position: absolute;
|
|
||||||
color: white;
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
padding: 0 5px;
|
|
||||||
&.custom-credit {
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
&.custom-caption {
|
|
||||||
bottom: 5px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,272 +0,0 @@
|
||||||
<!-- @component `PhotoCarousel` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-multimedia-photocarousel--docs) -->
|
|
||||||
<script lang="ts">
|
|
||||||
// Utils
|
|
||||||
import '@splidejs/svelte-splide/css/core';
|
|
||||||
import { fly } from 'svelte/transition';
|
|
||||||
import { Splide, SplideSlide, SplideTrack } from '@splidejs/svelte-splide';
|
|
||||||
|
|
||||||
// Icons
|
|
||||||
import Fa from 'svelte-fa';
|
|
||||||
import {
|
|
||||||
faChevronLeft,
|
|
||||||
faChevronRight,
|
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
|
|
||||||
// Components
|
|
||||||
import Block from '../Block/Block.svelte';
|
|
||||||
import PaddingReset from '../PaddingReset/PaddingReset.svelte';
|
|
||||||
|
|
||||||
// Types
|
|
||||||
import type { MoveEventDetail } from '@splidejs/svelte-splide/types';
|
|
||||||
import type { Snippet } from 'svelte';
|
|
||||||
import type { PhotoCarouselImage } from '../@types/global';
|
|
||||||
|
|
||||||
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
|
|
||||||
|
|
||||||
type ObjectFit = 'cover' | 'contain';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/** Array of images. */
|
|
||||||
images: PhotoCarouselImage[];
|
|
||||||
/** Width of the component within the text well: normal, wide, wider, widest, fluid */
|
|
||||||
width?: ContainerWidth;
|
|
||||||
/**
|
|
||||||
* Set a different width for captions within the text well, e.g. "normal," to keep captions inline with the rest of the text well. Can't ever be wider than `width`.
|
|
||||||
*/
|
|
||||||
textWidth?: ContainerWidth;
|
|
||||||
/** Add an ID to target with SCSS. */
|
|
||||||
id?: string;
|
|
||||||
/** Add a class to target with SCSS. */
|
|
||||||
cls?: string;
|
|
||||||
/** Max height of the carousel */
|
|
||||||
maxHeight?: number;
|
|
||||||
/** Default Image object-fit style: cover, contain */
|
|
||||||
defaultImageObjectFit?: ObjectFit;
|
|
||||||
/** Default image object-position style, e.g., `center center` or `50% 50%`. */
|
|
||||||
defaultImageObjectPosition?: string;
|
|
||||||
/** ARIA label for the carousel. */
|
|
||||||
carouselAriaLabel?: string;
|
|
||||||
/** Set height of the carousel as a ratio of its width as long as its below whatever you set in `maxHeight`. */
|
|
||||||
heightRatio?: number;
|
|
||||||
/** Number of images to preload ahead of the active image. */
|
|
||||||
preloadImages?: number;
|
|
||||||
/** Optional custom credit format as a snippet, which takes the argument `photo`. */
|
|
||||||
credit?: Snippet<[PhotoCarouselImage]>;
|
|
||||||
/** Optional custom caption format as a snippet, which takes the argument `photo`. */
|
|
||||||
caption?: Snippet<[PhotoCarouselImage]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {
|
|
||||||
width = 'wider',
|
|
||||||
textWidth = 'normal',
|
|
||||||
id = '',
|
|
||||||
cls = '',
|
|
||||||
images,
|
|
||||||
maxHeight = 660,
|
|
||||||
defaultImageObjectFit = 'cover',
|
|
||||||
defaultImageObjectPosition = 'center center',
|
|
||||||
carouselAriaLabel = 'Photo gallery',
|
|
||||||
heightRatio = 0.68,
|
|
||||||
preloadImages = 1,
|
|
||||||
credit,
|
|
||||||
caption,
|
|
||||||
}: Props = $props();
|
|
||||||
|
|
||||||
let containerWidth: number | undefined = $state(undefined);
|
|
||||||
let activeImageIndex = $state(0);
|
|
||||||
|
|
||||||
// Derive carousel height based on container width
|
|
||||||
let carouselHeight = $derived(
|
|
||||||
containerWidth ?
|
|
||||||
Math.min(containerWidth * heightRatio, maxHeight)
|
|
||||||
: maxHeight
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleActiveChange = (e?: CustomEvent<MoveEventDetail>) => {
|
|
||||||
if (!e) return;
|
|
||||||
activeImageIndex = e.detail.dest;
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Block {width} {id} class="photo-carousel fmy-6 {cls}">
|
|
||||||
<div class="carousel-container" bind:clientWidth={containerWidth}>
|
|
||||||
<Splide
|
|
||||||
hasTrack={false}
|
|
||||||
options={{
|
|
||||||
height: carouselHeight,
|
|
||||||
fixedHeight: carouselHeight,
|
|
||||||
lazyLoad: 'nearby',
|
|
||||||
preloadPages: preloadImages,
|
|
||||||
}}
|
|
||||||
aria-label={carouselAriaLabel}
|
|
||||||
on:move={handleActiveChange}
|
|
||||||
>
|
|
||||||
<div class="image-container">
|
|
||||||
<SplideTrack>
|
|
||||||
{#each images as image}
|
|
||||||
<SplideSlide>
|
|
||||||
<div class="photo-slide w-full h-full relative">
|
|
||||||
<figure
|
|
||||||
class="fm-0 w-full relative"
|
|
||||||
style="height: {carouselHeight}px;"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
class="w-full h-full fmy-0"
|
|
||||||
data-splide-lazy={image.src}
|
|
||||||
alt={image.altText}
|
|
||||||
style:object-fit={image.objectFit || defaultImageObjectFit}
|
|
||||||
style:object-position={image.objectPosition ||
|
|
||||||
defaultImageObjectPosition}
|
|
||||||
/>
|
|
||||||
<!-- Render custom credit if credit snippet and string both exist -->
|
|
||||||
{#if credit && image.credit}
|
|
||||||
{@render credit(image)}
|
|
||||||
|
|
||||||
<!-- Otherwise, render with default credit style -->
|
|
||||||
{:else if image.credit}
|
|
||||||
<span
|
|
||||||
class="credit absolute fmb-1 fml-1 leading-tighter font-note text-xxs"
|
|
||||||
class:contain-fit={image.objectFit === 'contain' ||
|
|
||||||
defaultImageObjectFit === 'contain'}
|
|
||||||
>{image.credit}</span
|
|
||||||
>
|
|
||||||
{/if}
|
|
||||||
</figure>
|
|
||||||
</div>
|
|
||||||
</SplideSlide>
|
|
||||||
{/each}
|
|
||||||
</SplideTrack>
|
|
||||||
|
|
||||||
{#if images[activeImageIndex].caption}
|
|
||||||
{@const activePhoto = images[activeImageIndex]}
|
|
||||||
<PaddingReset containerIsFluid={width === 'fluid'}>
|
|
||||||
<Block width={textWidth}>
|
|
||||||
<!-- Render custom caption if caption snippet and string both exist -->
|
|
||||||
{#if caption && activePhoto.caption}
|
|
||||||
{#key activeImageIndex}
|
|
||||||
{@render caption(activePhoto)}
|
|
||||||
{/key}
|
|
||||||
|
|
||||||
<!-- Otherwise, render with default caption style -->
|
|
||||||
{:else if activePhoto.caption}
|
|
||||||
{#key activeImageIndex}
|
|
||||||
<p
|
|
||||||
class="caption body-caption text-center"
|
|
||||||
in:fly|local={{ x: 20, duration: 175 }}
|
|
||||||
>
|
|
||||||
{activePhoto.caption}
|
|
||||||
</p>
|
|
||||||
{/key}
|
|
||||||
{/if}
|
|
||||||
</Block>
|
|
||||||
</PaddingReset>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="splide__progress">
|
|
||||||
<div class="splide__progress__bar"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splide__arrows fp-1">
|
|
||||||
<button class="splide__arrow splide__arrow--prev">
|
|
||||||
<Fa icon={faChevronLeft} fw />
|
|
||||||
</button>
|
|
||||||
<button class="splide__arrow splide__arrow--next">
|
|
||||||
<Fa icon={faChevronRight} fw />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Splide>
|
|
||||||
</div>
|
|
||||||
</Block>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@use '../../scss/mixins' as mixins;
|
|
||||||
|
|
||||||
.carousel-container {
|
|
||||||
.photo-slide {
|
|
||||||
figure {
|
|
||||||
span.credit {
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
color: white;
|
|
||||||
text-shadow:
|
|
||||||
-1px -1px 0 #333,
|
|
||||||
1px -1px 0 #333,
|
|
||||||
-1px 1px 0 #333,
|
|
||||||
1px 1px 0 #333;
|
|
||||||
&.contain-fit {
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 0%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
:global(.splide) {
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
:global(li) {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows) {
|
|
||||||
width: 275px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button) {
|
|
||||||
display: flex;
|
|
||||||
font-size: 14px;
|
|
||||||
height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
@include mixins.text-secondary;
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button.splide__arrow--prev) {
|
|
||||||
padding-right: 7px;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button.splide__arrow--next) {
|
|
||||||
padding-left: 7px;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button:hover) {
|
|
||||||
opacity: 1;
|
|
||||||
border-color: mixins.$theme-colour-text-secondary;
|
|
||||||
@include mixins.text-secondary;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button:disabled) {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
:global(.splide__arrows button:disabled:hover) {
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
:global(ul.splide__pagination) {
|
|
||||||
width: 200px;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
margin: -26px auto 0;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
:global(ul.splide__pagination li) {
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-top: -9px;
|
|
||||||
}
|
|
||||||
:global(ul.splide__pagination li button) {
|
|
||||||
width: 100%;
|
|
||||||
height: 7px;
|
|
||||||
border-radius: 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 1px solid mixins.$theme-colour-background;
|
|
||||||
background: mixins.$theme-colour-text-secondary;
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
:global(ul.splide__pagination li button.is-active) {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194630Z_544493697_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets and Aymeric Laporte react before a Germany goal is disallowed following a VAR review.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194619Z_2007900040_UP1.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets fouls Germany's Jamal Musiala before being shown yellow card.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194619Z_635809122_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets is shown a yellow card by referee Danny Desmond Makkelie.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T191015Z_1293757566_UP1.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets in action with Germany's Thomas Muller.",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T181411Z_1_MTZXEIBR0QNN.jpeg",
|
|
||||||
"caption": "Spain fans inside the stadium before the match.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194827Z_345059331_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Gavi.",
|
|
||||||
"credit": "REUTERS/Fabrizio Bensch"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T175149Z_1_MTZXEIBR0PMD.jpeg",
|
|
||||||
"caption": "",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T203232Z_890709671_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Alvaro Morata scores their first goal.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T203612Z_1399473226_UP1.jpeg",
|
|
||||||
"caption": "Spain's Alvaro Morata celebrates scoring their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T204305Z_1795686896_UP1.jpeg",
|
|
||||||
"caption": "Germany's Niclas Fullkrug scores their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T204528Z_151067034_UP1E.jpeg",
|
|
||||||
"caption": "Germany's Niclas Fullkrug celebrates scoring their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205041Z_2076149593_UP1.jpeg",
|
|
||||||
"caption": "Spain coach Luis Enrique.",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205604Z_1468073277_UP1.jpeg",
|
|
||||||
"caption": "Germany's Manuel Neuer applauds fans after the match.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205854Z_408619749_UP1E.jpeg",
|
|
||||||
"caption": "Spain players applaud fans after the match.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194630Z_544493697_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets and Aymeric Laporte react before a Germany goal is disallowed following a VAR review.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194619Z_2007900040_UP1.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets fouls Germany's Jamal Musiala before being shown yellow card.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194619Z_635809122_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets is shown a yellow card by referee Danny Desmond Makkelie.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T191015Z_1293757566_UP1.jpeg",
|
|
||||||
"caption": "Spain's Sergio Busquets in action with Germany's Thomas Muller.",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T181411Z_1_MTZXEIBR0QNN.jpeg",
|
|
||||||
"caption": "Spain fans inside the stadium before the match.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T194827Z_345059331_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Gavi.",
|
|
||||||
"credit": "REUTERS/Fabrizio Bensch"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T175149Z_1_MTZXEIBR0PMD.jpeg",
|
|
||||||
"caption": "",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T203232Z_890709671_UP1E.jpeg",
|
|
||||||
"caption": "Spain's Alvaro Morata scores their first goal.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T203612Z_1399473226_UP1.jpeg",
|
|
||||||
"caption": "Spain's Alvaro Morata celebrates scoring their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T204305Z_1795686896_UP1.jpeg",
|
|
||||||
"caption": "Germany's Niclas Fullkrug scores their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T204528Z_151067034_UP1E.jpeg",
|
|
||||||
"caption": "Germany's Niclas Fullkrug celebrates scoring their first goal.",
|
|
||||||
"credit": "REUTERS/Molly Darlington"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205041Z_2076149593_UP1.jpeg",
|
|
||||||
"caption": "Spain coach Luis Enrique.",
|
|
||||||
"credit": "REUTERS/John Sibley"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205604Z_1468073277_UP1.jpeg",
|
|
||||||
"caption": "Germany's Manuel Neuer applauds fans after the match.",
|
|
||||||
"credit": "REUTERS/Kai Pfaffenbach"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "https://graphics.thomsonreuters.com/cdn/django-tools/media/graphics-gallery/galleries/world-cup-2022/spain-germany-11-27/2022-11-27T205854Z_408619749_UP1E.jpeg",
|
|
||||||
"caption": "Spain players applaud fans after the match.",
|
|
||||||
"credit": "REUTERS/Albert Gea"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -27,7 +27,6 @@ export { default as InlineAd } from './components/AdSlot/InlineAd.svelte';
|
||||||
export { default as LeaderboardAd } from './components/AdSlot/LeaderboardAd.svelte';
|
export { default as LeaderboardAd } from './components/AdSlot/LeaderboardAd.svelte';
|
||||||
export { default as Markdown } from './components/Markdown/Markdown.svelte';
|
export { default as Markdown } from './components/Markdown/Markdown.svelte';
|
||||||
export { default as PaddingReset } from './components/PaddingReset/PaddingReset.svelte';
|
export { default as PaddingReset } from './components/PaddingReset/PaddingReset.svelte';
|
||||||
export { default as PhotoCarousel } from './components/PhotoCarousel/PhotoCarousel.svelte';
|
|
||||||
export { default as PhotoPack } from './components/PhotoPack/PhotoPack.svelte';
|
export { default as PhotoPack } from './components/PhotoPack/PhotoPack.svelte';
|
||||||
export { default as PymChild } from './components/PymChild/PymChild.svelte';
|
export { default as PymChild } from './components/PymChild/PymChild.svelte';
|
||||||
export { pym } from './components/PymChild/state.svelte.js';
|
export { pym } from './components/PymChild/state.svelte.js';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue