set up photo pack
This commit is contained in:
parent
894ff8442d
commit
e9dff42de1
101 changed files with 848 additions and 892 deletions
|
|
@ -28,7 +28,7 @@
|
||||||
import SharkImg from './stories/shark.jpg';
|
import SharkImg from './stories/shark.jpg';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<YourComponent {...args} />
|
<YourComponent {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -36,9 +36,9 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
src: SharkImg,
|
src: SharkImg,
|
||||||
altText: "Duh dum! It's a shark!!",
|
altText: "Duh dum! It's a shark!!",
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@
|
||||||
|
|
||||||
<Block {width} {id} class="photo {cls}">
|
<Block {width} {id} class="photo {cls}">
|
||||||
<div
|
<div
|
||||||
style:background-image="{`url(${src})`}"
|
style:background-image={`url(${src})`}
|
||||||
style:height="{`${height}px`}"
|
style:height={`${height}px`}
|
||||||
></div>
|
></div>
|
||||||
<p class="visually-hidden">{altText}</p>
|
<p class="visually-hidden">{altText}</p>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ An action you can use to easily set [CSS variables](https://developer.mozilla.or
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Attach it to a parent element with the action -->
|
<!-- Attach it to a parent element with the action -->
|
||||||
<div use:cssVariables="{variables}">
|
<div use:cssVariables={variables}>
|
||||||
<p>My text...</p>
|
<p>My text...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ An action you can use to easily to check when a DOM element's dimensions change
|
||||||
let elementWidth = 0;
|
let elementWidth = 0;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div use:resizeObserver="{(element) => (elementWidth = element.clientWidth)}">
|
<div use:resizeObserver={(element) => (elementWidth = element.clientWidth)}>
|
||||||
My width is: {elementWidth}
|
My width is: {elementWidth}
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div data-freestar-ad="{dataFreestarAd || null}" id="{adId}"></div>
|
<div data-freestar-ad={dataFreestarAd || null} id={adId}></div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(div.freestar-adslot:has(.unfulfilled-ad)) {
|
:global(div.freestar-adslot:has(.unfulfilled-ad)) {
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,11 @@ You may add **up to three** inline ads per page, but must set the `n` prop on mu
|
||||||
|
|
||||||
```svelte
|
```svelte
|
||||||
<!-- First inline ad on the page -->
|
<!-- First inline ad on the page -->
|
||||||
<InlineAd n="{1}" />
|
<InlineAd n={1} />
|
||||||
<!-- ... second ... -->
|
<!-- ... second ... -->
|
||||||
<InlineAd n="{2}" />
|
<InlineAd n={2} />
|
||||||
<!-- ... third and final. -->
|
<!-- ... third and final. -->
|
||||||
<InlineAd n="{3}" />
|
<InlineAd n={3} />
|
||||||
```
|
```
|
||||||
|
|
||||||
<Canvas of={InlineAdStories.Demo} />
|
<Canvas of={InlineAdStories.Demo} />
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerWidth="{windowWidth}" />
|
<svelte:window bind:innerWidth={windowWidth} />
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="freestar-adslot leaderboard__sticky {cls}"
|
class="freestar-adslot leaderboard__sticky {cls}"
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
let adType = $derived(getAdType(placementName));
|
let adType = $derived(getAdType(placementName));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerWidth="{windowWidth}" />
|
<svelte:window bind:innerWidth={windowWidth} />
|
||||||
|
|
||||||
{#if windowWidth}
|
{#if windowWidth}
|
||||||
{#key placementName}
|
{#key placementName}
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@ You can set custom column widths by passing an object to the `columnWidths` prop
|
||||||
```svelte
|
```svelte
|
||||||
<!-- Set custom column widths -->
|
<!-- Set custom column widths -->
|
||||||
<Article
|
<Article
|
||||||
columnWidths="{{
|
columnWidths={{
|
||||||
narrower: 310,
|
narrower: 310,
|
||||||
narrow: 450,
|
narrow: 450,
|
||||||
normal: 550,
|
normal: 550,
|
||||||
wide: 675,
|
wide: 675,
|
||||||
wider: 1400,
|
wider: 1400,
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<!-- Custom column widths get passed down to the `Block` component -->
|
<!-- Custom column widths get passed down to the `Block` component -->
|
||||||
<Block width="narrower" />
|
<Block width="narrower" />
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
import Article from '../Article/Article.svelte';
|
import Article from '../Article/Article.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Article id="block-demo-article">
|
<Article id="block-demo-article">
|
||||||
<div class="article-boundaries">
|
<div class="article-boundaries">
|
||||||
|
|
@ -51,9 +51,9 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="Custom layouts" {...withStoryDocs(customLayoutsDocs)}>
|
<Story name="Custom layouts" {...withStoryDocs(customLayoutsDocs)}>
|
||||||
|
|
@ -77,42 +77,41 @@
|
||||||
<Article id="block-demo-article">
|
<Article id="block-demo-article">
|
||||||
<div class="article-boundaries">
|
<div class="article-boundaries">
|
||||||
<div class="label">Article</div>
|
<div class="label">Article</div>
|
||||||
<Block width="narrower" snap="{true}" class="block-snap-widths-demo"
|
<Block width="narrower" snap={true} class="block-snap-widths-demo"
|
||||||
>narrower</Block
|
>narrower</Block
|
||||||
>
|
>
|
||||||
<Block width="narrow" snap="{true}" class="block-snap-widths-demo"
|
<Block width="narrow" snap={true} class="block-snap-widths-demo"
|
||||||
>narrow</Block
|
>narrow</Block
|
||||||
>
|
>
|
||||||
<Block width="normal" snap="{true}" class="block-snap-widths-demo"
|
<Block width="normal" snap={true} class="block-snap-widths-demo"
|
||||||
>normal</Block
|
>normal</Block
|
||||||
>
|
>
|
||||||
<Block width="wide" snap="{true}" class="block-snap-widths-demo"
|
<Block width="wide" snap={true} class="block-snap-widths-demo">wide</Block
|
||||||
>wide</Block
|
|
||||||
>
|
>
|
||||||
<Block width="wider" snap="{true}" class="block-snap-widths-demo"
|
<Block width="wider" snap={true} class="block-snap-widths-demo"
|
||||||
>wider</Block
|
>wider</Block
|
||||||
>
|
>
|
||||||
<Block width="narrower" snap="{true}" class="block-snap-widths-demo even"
|
<Block width="narrower" snap={true} class="block-snap-widths-demo even"
|
||||||
>narrower</Block
|
>narrower</Block
|
||||||
>
|
>
|
||||||
<Block width="narrow" snap="{true}" class="block-snap-widths-demo even"
|
<Block width="narrow" snap={true} class="block-snap-widths-demo even"
|
||||||
>narrow</Block
|
>narrow</Block
|
||||||
>
|
>
|
||||||
<Block
|
<Block
|
||||||
width="normal"
|
width="normal"
|
||||||
snap="{true}"
|
snap={true}
|
||||||
class="block-snap-widths-demo even skip-narrow"
|
class="block-snap-widths-demo even skip-narrow"
|
||||||
>normal.skip-narrow</Block
|
>normal.skip-narrow</Block
|
||||||
>
|
>
|
||||||
<Block
|
<Block
|
||||||
width="wide"
|
width="wide"
|
||||||
snap="{true}"
|
snap={true}
|
||||||
class="block-snap-widths-demo even skip-normal skip-narrow"
|
class="block-snap-widths-demo even skip-normal skip-narrow"
|
||||||
>wide.skip-normal.skip-narrow</Block
|
>wide.skip-normal.skip-narrow</Block
|
||||||
>
|
>
|
||||||
<Block
|
<Block
|
||||||
width="wider"
|
width="wider"
|
||||||
snap="{true}"
|
snap={true}
|
||||||
class="block-snap-widths-demo even skip-wide">wider.skip-wide</Block
|
class="block-snap-widths-demo even skip-wide">wider.skip-wide</Block
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -145,9 +144,9 @@
|
||||||
background: rgb(211, 132, 123);
|
background: rgb(211, 132, 123);
|
||||||
}
|
}
|
||||||
:global(
|
:global(
|
||||||
#block-demo-article .label,
|
#block-demo-article .label,
|
||||||
#block-demo-article div.article-block.block-snap-widths-demo
|
#block-demo-article div.article-block.block-snap-widths-demo
|
||||||
) {
|
) {
|
||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@
|
||||||
<div
|
<div
|
||||||
{id}
|
{id}
|
||||||
class="article-block fmx-auto {width} {cls}"
|
class="article-block fmx-auto {width} {cls}"
|
||||||
class:snap="{snap && width !== 'fluid' && width !== 'widest'}"
|
class:snap={snap && width !== 'fluid' && width !== 'widest'}
|
||||||
{role}
|
{role}
|
||||||
aria-label="{ariaLabel}"
|
aria-label={ariaLabel}
|
||||||
>
|
>
|
||||||
<!-- block content -->
|
<!-- block content -->
|
||||||
<slot />
|
<slot />
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,18 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Demo"
|
name="Demo"
|
||||||
args="{{
|
args={{
|
||||||
src: 'https://reuters.com/graphics/USA-ABORTION/lgpdwggnwvo/media-embed.html',
|
src: 'https://reuters.com/graphics/USA-ABORTION/lgpdwggnwvo/media-embed.html',
|
||||||
id: 'abortion-rights-map',
|
id: 'abortion-rights-map',
|
||||||
ariaLabel: 'map',
|
ariaLabel: 'map',
|
||||||
frameTitle: 'Global abortion access',
|
frameTitle: 'Global abortion access',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="With chatter"
|
name="With chatter"
|
||||||
tags="{['!autodocs']}"
|
tags={['!autodocs']}
|
||||||
args="{{
|
args={{
|
||||||
frameTitle: 'Global abortion access',
|
frameTitle: 'Global abortion access',
|
||||||
ariaLabel: 'map',
|
ariaLabel: 'map',
|
||||||
id: 'abortion-rights-map',
|
id: 'abortion-rights-map',
|
||||||
|
|
@ -37,5 +37,5 @@
|
||||||
description: 'A map of worldwide access to abortion.',
|
description: 'A map of worldwide access to abortion.',
|
||||||
notes:
|
notes:
|
||||||
'Note: Different indicators and additional restrictions, including different gestational limits, apply in some countries. Refer to source for full classification. Current as of May 4, 2022.\n\nSource: Center for Reproductive Rights',
|
'Note: Different indicators and additional restrictions, including different gestational limits, apply in some countries. Refer to source for full classification. Current as of May 4, 2022.\n\nSource: Center for Reproductive Rights',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<DocumentCloud {...args} />
|
<DocumentCloud {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -30,9 +30,9 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
slug: '3259984-Trump-Intelligence-Allegations',
|
slug: '3259984-Trump-Intelligence-Allegations',
|
||||||
altText: 'These Reports Allege Trump Has Deep Ties To Russia',
|
altText: 'These Reports Allege Trump Has Deep Ties To Russia',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
<iframe
|
<iframe
|
||||||
class="h-screen"
|
class="h-screen"
|
||||||
src="https://embed.documentcloud.org/documents/{slug}/?embed=1&responsive=1&title=1"
|
src="https://embed.documentcloud.org/documents/{slug}/?embed=1&responsive=1&title=1"
|
||||||
title="{altText}"
|
title={altText}
|
||||||
width="700"
|
width="700"
|
||||||
height="540"
|
height="540"
|
||||||
sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-popups-to-escape-sandbox"
|
sandbox="allow-scripts allow-same-origin allow-popups allow-forms allow-popups-to-escape-sandbox"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script module lang="ts">
|
<script module lang="ts">
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||||
|
|
||||||
// @ts-ignore raw
|
// @ts-ignore raw
|
||||||
import componentDocs from './stories/docs/component.md?raw';
|
import componentDocs from './stories/docs/component.md?raw';
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
// withStoryDocs,
|
// withStoryDocs,
|
||||||
// } from '$lib/docs/utils/withParams.js';
|
// } from '$lib/docs/utils/withParams.js';
|
||||||
|
|
||||||
|
|
||||||
const { Story } = defineMeta({
|
const { Story } = defineMeta({
|
||||||
title: 'Components/Multimedia/FeaturePhoto',
|
title: 'Components/Multimedia/FeaturePhoto',
|
||||||
component: FeaturePhoto,
|
component: FeaturePhoto,
|
||||||
|
|
@ -39,34 +38,33 @@
|
||||||
import sharkSrc from './stories/shark.jpg';
|
import sharkSrc from './stories/shark.jpg';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
src: sharkSrc,
|
src: sharkSrc,
|
||||||
altText: 'A shark!',
|
altText: 'A shark!',
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
caption: 'Carcharodon carcharias - REUTERS',
|
caption: 'Carcharodon carcharias - REUTERS',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="ArchieML"
|
name="ArchieML"
|
||||||
args="{{
|
args={{
|
||||||
src: sharkSrc,
|
src: sharkSrc,
|
||||||
altText: 'A shark!',
|
altText: 'A shark!',
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
caption: 'Carcharodon carcharias - REUTERS',
|
caption: 'Carcharodon carcharias - REUTERS',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
<!-- {...withStoryDocs(archieMLDocs)} -->
|
<!-- {...withStoryDocs(archieMLDocs)} -->
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Missing altText"
|
name="Missing altText"
|
||||||
args="{{
|
args={{
|
||||||
src: sharkSrc,
|
src: sharkSrc,
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
caption: 'Carcharodon carcharias - REUTERS',
|
caption: 'Carcharodon carcharias - REUTERS',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
<!-- {...withStoryDocs(missingAltTextDocs)} -->
|
<!-- {...withStoryDocs(missingAltTextDocs)} -->
|
||||||
|
|
|
||||||
|
|
@ -93,18 +93,18 @@
|
||||||
|
|
||||||
<Block {width} class="photo fmy-6 {cls}" {id}>
|
<Block {width} class="photo fmy-6 {cls}" {id}>
|
||||||
<figure
|
<figure
|
||||||
bind:this="{container}"
|
bind:this={container}
|
||||||
aria-label="media"
|
aria-label="media"
|
||||||
class="w-full flex flex-col relative"
|
class="w-full flex flex-col relative"
|
||||||
>
|
>
|
||||||
{#if !lazy || (intersectable && intersecting)}
|
{#if !lazy || (intersectable && intersecting)}
|
||||||
<img class="w-full my-0" {src} alt="{altText}" />
|
<img class="w-full my-0" {src} alt={altText} />
|
||||||
{:else}
|
{:else}
|
||||||
<div class="placeholder w-full" style="{`height: ${height}px;`}"></div>
|
<div class="placeholder w-full" style={`height: ${height}px;`}></div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if caption}
|
{#if caption}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<Block width="{textWidth}" class="notes w-full fmy-0">
|
<Block width={textWidth} class="notes w-full fmy-0">
|
||||||
<figcaption>
|
<figcaption>
|
||||||
{caption}
|
{caption}
|
||||||
</figcaption>
|
</figcaption>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Framer {...args} />
|
<Framer {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
embeds: [
|
embeds: [
|
||||||
'https://graphics.reuters.com/USA-CONGRESS/FUNDRAISING/zjvqkawjlvx/embeds/en/embed/?zzz',
|
'https://graphics.reuters.com/USA-CONGRESS/FUNDRAISING/zjvqkawjlvx/embeds/en/embed/?zzz',
|
||||||
],
|
],
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -62,25 +62,20 @@
|
||||||
|
|
||||||
<div id="typeahead-container">
|
<div id="typeahead-container">
|
||||||
<div class="embed-link">
|
<div class="embed-link">
|
||||||
<a
|
<a rel="external" target="_blank" href={activeEmbed} title={activeEmbed}>
|
||||||
rel="external"
|
Live link <Fa icon={faLink} />
|
||||||
target="_blank"
|
|
||||||
href="{activeEmbed}"
|
|
||||||
title="{activeEmbed}"
|
|
||||||
>
|
|
||||||
Live link <Fa icon="{faLink}" />
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<Typeahead
|
<Typeahead
|
||||||
label="Select an embed"
|
label="Select an embed"
|
||||||
value="{embedTitles[embeds.indexOf(activeEmbed)] ||
|
value={embedTitles[embeds.indexOf(activeEmbed)] ||
|
||||||
embedTitles[activeEmbedIndex] ||
|
embedTitles[activeEmbedIndex] ||
|
||||||
embedTitles[0]}"
|
embedTitles[0]}
|
||||||
extract="{(d) => embedTitles[d.index]}"
|
extract={(d) => embedTitles[d.index]}
|
||||||
data="{embeds.map((embed, index) => ({ index, embed }))}"
|
data={embeds.map((embed, index) => ({ index, embed }))}
|
||||||
placeholder="{'Search'}"
|
placeholder={'Search'}
|
||||||
showDropdownOnFocus="{true}"
|
showDropdownOnFocus={true}
|
||||||
on:select="{({ detail }) => {
|
on:select={({ detail }) => {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
window.localStorage.setItem(
|
window.localStorage.setItem(
|
||||||
'framer-active-embed',
|
'framer-active-embed',
|
||||||
|
|
@ -89,7 +84,7 @@
|
||||||
}
|
}
|
||||||
activeEmbed = detail.original.embed;
|
activeEmbed = detail.original.embed;
|
||||||
activeEmbedIndex = detail.original.index;
|
activeEmbedIndex = detail.original.index;
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -101,7 +96,7 @@
|
||||||
|
|
||||||
<div id="home-link">
|
<div id="home-link">
|
||||||
<a rel="external" href="./../">
|
<a rel="external" href="./../">
|
||||||
<Fa icon="{faDesktop}" />
|
<Fa icon={faDesktop} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,48 +95,48 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
onmousemove="{move}"
|
onmousemove={move}
|
||||||
onmouseup="{end}"
|
onmouseup={end}
|
||||||
onkeydown="{handleKeyDown}"
|
onkeydown={handleKeyDown}
|
||||||
bind:innerWidth="{windowInnerWidth}"
|
bind:innerWidth={windowInnerWidth}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div id="resizer">
|
<div id="resizer">
|
||||||
<div class="slider">
|
<div class="slider">
|
||||||
<div class="label" style="{`opacity: ${sliding || isFocused ? 1 : 0};`}">
|
<div class="label" style={`opacity: ${sliding || isFocused ? 1 : 0};`}>
|
||||||
{pixelLabel || $width}px
|
{pixelLabel || $width}px
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="icon left"
|
class="icon left"
|
||||||
disabled="{$width === minWidth}"
|
disabled={$width === minWidth}
|
||||||
onclick="{decrement}"
|
onclick={decrement}
|
||||||
onfocus="{onFocus}"
|
onfocus={onFocus}
|
||||||
onmouseover="{onFocus}"
|
onmouseover={onFocus}
|
||||||
onmouseleave="{onBlur}"
|
onmouseleave={onBlur}
|
||||||
>
|
>
|
||||||
<Fa icon="{faMobileAlt}" fw />
|
<Fa icon={faMobileAlt} fw />
|
||||||
</button>
|
</button>
|
||||||
<div class="slider-container" bind:this="{container}">
|
<div class="slider-container" bind:this={container}>
|
||||||
<div class="track"></div>
|
<div class="track"></div>
|
||||||
<div
|
<div
|
||||||
class="handle"
|
class="handle"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
role="button"
|
role="button"
|
||||||
style="left: calc({offset * 100}% - 5px);"
|
style="left: calc({offset * 100}% - 5px);"
|
||||||
onmousedown="{start}"
|
onmousedown={start}
|
||||||
onfocus="{onFocus}"
|
onfocus={onFocus}
|
||||||
onblur="{onBlur}"
|
onblur={onBlur}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="icon right"
|
class="icon right"
|
||||||
disabled="{$width === maxWidth}"
|
disabled={$width === maxWidth}
|
||||||
onclick="{increment}"
|
onclick={increment}
|
||||||
onfocus="{onFocus}"
|
onfocus={onFocus}
|
||||||
onmouseover="{onFocus}"
|
onmouseover={onFocus}
|
||||||
onmouseleave="{onBlur}"
|
onmouseleave={onBlur}
|
||||||
>
|
>
|
||||||
<Fa icon="{faDesktop}" fw />
|
<Fa icon={faDesktop} fw />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -158,55 +158,55 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
on:click="{({ target }) => {
|
on:click={({ target }) => {
|
||||||
if (!hideDropdown && !comboboxRef?.contains(target)) {
|
if (!hideDropdown && !comboboxRef?.contains(target)) {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-svelte-typeahead
|
data-svelte-typeahead
|
||||||
bind:this="{comboboxRef}"
|
bind:this={comboboxRef}
|
||||||
role="combobox"
|
role="combobox"
|
||||||
aria-haspopup="listbox"
|
aria-haspopup="listbox"
|
||||||
aria-owns="{id}-listbox"
|
aria-owns="{id}-listbox"
|
||||||
class:dropdown="{results.length > 0}"
|
class:dropdown={results.length > 0}
|
||||||
aria-controls="{id}-listbox"
|
aria-controls="{id}-listbox"
|
||||||
aria-expanded="{showResults ||
|
aria-expanded={showResults ||
|
||||||
(isFocused && value.length > 0 && results.length === 0)}"
|
(isFocused && value.length > 0 && results.length === 0)}
|
||||||
id="{id}-typeahead"
|
id="{id}-typeahead"
|
||||||
>
|
>
|
||||||
<Search
|
<Search
|
||||||
{id}
|
{id}
|
||||||
removeFormAriaAttributes="{true}"
|
removeFormAriaAttributes={true}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
bind:ref="{searchRef}"
|
bind:ref={searchRef}
|
||||||
aria-autocomplete="list"
|
aria-autocomplete="list"
|
||||||
aria-controls="{id}-listbox"
|
aria-controls="{id}-listbox"
|
||||||
aria-labelledby="{id}-label"
|
aria-labelledby="{id}-label"
|
||||||
aria-activedescendant="{(
|
aria-activedescendant={(
|
||||||
selectedIndex >= 0 && !hideDropdown && results.length > 0
|
selectedIndex >= 0 && !hideDropdown && results.length > 0
|
||||||
) ?
|
) ?
|
||||||
`${id}-result-${selectedIndex}`
|
`${id}-result-${selectedIndex}`
|
||||||
: null}"
|
: null}
|
||||||
bind:value
|
bind:value
|
||||||
on:type
|
on:type
|
||||||
on:input
|
on:input
|
||||||
on:change
|
on:change
|
||||||
on:focus
|
on:focus
|
||||||
on:focus="{() => {
|
on:focus={() => {
|
||||||
open();
|
open();
|
||||||
if (showDropdownOnFocus) {
|
if (showDropdownOnFocus) {
|
||||||
showResults = true;
|
showResults = true;
|
||||||
isFocused = true;
|
isFocused = true;
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
on:clear
|
on:clear
|
||||||
on:clear="{open}"
|
on:clear={open}
|
||||||
on:blur
|
on:blur
|
||||||
on:keydown
|
on:keydown
|
||||||
on:keydown="{(e) => {
|
on:keydown={(e) => {
|
||||||
if (results.length === 0) return;
|
if (results.length === 0) return;
|
||||||
|
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
|
|
@ -228,10 +228,10 @@
|
||||||
close();
|
close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
<ul
|
<ul
|
||||||
class:svelte-typeahead-list="{true}"
|
class:svelte-typeahead-list={true}
|
||||||
role="listbox"
|
role="listbox"
|
||||||
aria-labelledby="{id}-label"
|
aria-labelledby="{id}-label"
|
||||||
id="{id}-listbox"
|
id="{id}-listbox"
|
||||||
|
|
@ -241,24 +241,24 @@
|
||||||
<li
|
<li
|
||||||
role="option"
|
role="option"
|
||||||
id="{id}-result-{index}"
|
id="{id}-result-{index}"
|
||||||
class:selected="{selectedIndex === index}"
|
class:selected={selectedIndex === index}
|
||||||
class:disabled="{result.disabled}"
|
class:disabled={result.disabled}
|
||||||
aria-selected="{selectedIndex === index}"
|
aria-selected={selectedIndex === index}
|
||||||
on:click="{() => {
|
on:click={() => {
|
||||||
if (result.disabled) return;
|
if (result.disabled) return;
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
select();
|
select();
|
||||||
}}"
|
}}
|
||||||
on:keyup="{(e) => {
|
on:keyup={(e) => {
|
||||||
if (e.key !== 'Enter') return;
|
if (e.key !== 'Enter') return;
|
||||||
if (result.disabled) return;
|
if (result.disabled) return;
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
select();
|
select();
|
||||||
}}"
|
}}
|
||||||
on:mouseenter="{() => {
|
on:mouseenter={() => {
|
||||||
if (result.disabled) return;
|
if (result.disabled) return;
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<slot {result} {index} {value}>
|
<slot {result} {index} {value}>
|
||||||
{@html result.string}
|
{@html result.string}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* Whether to wrap the graphic with an aria hidden tag.
|
* Whether to wrap the graphic with an aria hidden tag.
|
||||||
*/
|
*/
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,11 @@
|
||||||
import PlaceholderImg from './stories/placeholder.png';
|
import PlaceholderImg from './stories/placeholder.png';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<GraphicBlock {...args}>
|
<GraphicBlock {...args}>
|
||||||
<div class="demo-graphic">
|
<div class="demo-graphic">
|
||||||
<img src="{PlaceholderImg}" alt="placeholder" />
|
<img src={PlaceholderImg} alt="placeholder" />
|
||||||
</div>
|
</div>
|
||||||
</GraphicBlock>
|
</GraphicBlock>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -52,14 +52,14 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
title: 'Bacon ipsum dolor amet t-bone',
|
title: 'Bacon ipsum dolor amet t-bone',
|
||||||
description:
|
description:
|
||||||
'Pork loin t-bone jowl prosciutto, short loin flank kevin tri-tip cupim pig pork. Meatloaf tri-tip frankfurter short ribs, cupim brisket bresaola chislic tail jerky burgdoggen pancetta.',
|
'Pork loin t-bone jowl prosciutto, short loin flank kevin tri-tip cupim pig pork. Meatloaf tri-tip frankfurter short ribs, cupim brisket bresaola chislic tail jerky burgdoggen pancetta.',
|
||||||
notes:
|
notes:
|
||||||
'Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)',
|
'Note: Data current as of Aug. 2, 2022.\n\nSource: [Google research](https://google.com)',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="ArchieML" {...withStoryDocs(archieMLDocs)}>
|
<Story name="ArchieML" {...withStoryDocs(archieMLDocs)}>
|
||||||
|
|
@ -76,18 +76,18 @@
|
||||||
<Story name="Custom text" {...withStoryDocs(customTextDocs)}>
|
<Story name="Custom text" {...withStoryDocs(customTextDocs)}>
|
||||||
<GraphicBlock width="normal">
|
<GraphicBlock width="normal">
|
||||||
{#snippet title()}
|
{#snippet title()}
|
||||||
<div >
|
<div>
|
||||||
<h5>My smaller title</h5>
|
<h5>My smaller title</h5>
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
<div class="demo-graphic">
|
<div class="demo-graphic">
|
||||||
<img src="{PlaceholderImg}" alt="placeholder" />
|
<img src={PlaceholderImg} alt="placeholder" />
|
||||||
</div>
|
</div>
|
||||||
{#snippet notes()}
|
{#snippet notes()}
|
||||||
<aside >
|
<aside>
|
||||||
<p><strong>Note:</strong> Data current as of Aug. 2, 2022.</p>
|
<p><strong>Note:</strong> Data current as of Aug. 2, 2022.</p>
|
||||||
</aside>
|
</aside>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</GraphicBlock>
|
</GraphicBlock>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,23 +76,23 @@
|
||||||
|
|
||||||
<Block {id} {snap} {role} {width} {ariaLabel} class="graphic fmy-6 {cls}">
|
<Block {id} {snap} {role} {width} {ariaLabel} class="graphic fmy-6 {cls}">
|
||||||
{#if $$slots.title}
|
{#if $$slots.title}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<TextBlock width="{textWidth}">
|
<TextBlock width={textWidth}>
|
||||||
<!-- Custom title content -->
|
<!-- Custom title content -->
|
||||||
<slot name="title" />
|
<slot name="title" />
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</PaddingReset>
|
</PaddingReset>
|
||||||
{:else if title}
|
{:else if title}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<TextBlock width="{textWidth}">
|
<TextBlock width={textWidth}>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
{#if description}
|
{#if description}
|
||||||
<Markdown source="{description}" />
|
<Markdown source={description} />
|
||||||
{/if}
|
{/if}
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</PaddingReset>
|
</PaddingReset>
|
||||||
{/if}
|
{/if}
|
||||||
<AriaHidden hidden="{!!$$slots.aria || !!ariaDescription}">
|
<AriaHidden hidden={!!$$slots.aria || !!ariaDescription}>
|
||||||
<!-- Graphic content -->
|
<!-- Graphic content -->
|
||||||
<slot />
|
<slot />
|
||||||
</AriaHidden>
|
</AriaHidden>
|
||||||
|
|
@ -102,22 +102,22 @@
|
||||||
<!-- Custom ARIA markup -->
|
<!-- Custom ARIA markup -->
|
||||||
<slot name="aria" />
|
<slot name="aria" />
|
||||||
{:else}
|
{:else}
|
||||||
<Markdown source="{ariaDescription}" />
|
<Markdown source={ariaDescription} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $$slots.notes}
|
{#if $$slots.notes}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<TextBlock width="{textWidth}">
|
<TextBlock width={textWidth}>
|
||||||
<!-- Custom notes content -->
|
<!-- Custom notes content -->
|
||||||
<slot name="notes" />
|
<slot name="notes" />
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</PaddingReset>
|
</PaddingReset>
|
||||||
{:else if notes}
|
{:else if notes}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<TextBlock width="{textWidth}">
|
<TextBlock width={textWidth}>
|
||||||
<aside>
|
<aside>
|
||||||
<Markdown source="{notes}" />
|
<Markdown source={notes} />
|
||||||
</aside>
|
</aside>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</PaddingReset>
|
</PaddingReset>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ContainerWidth } from '../@types/global';
|
import type { ContainerWidth } from '../@types/global';
|
||||||
|
|
||||||
|
|
||||||
import Block from '../Block/Block.svelte';
|
import Block from '../Block/Block.svelte';
|
||||||
interface Props {
|
interface Props {
|
||||||
/** Width of the component within the text well. */
|
/** Width of the component within the text well. */
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<!-- Generated by ai2html v0.100.0 - 2021-09-29 12:37 -->
|
<!-- Generated by ai2html v0.100.0 - 2021-09-29 12:37 -->
|
||||||
|
|
||||||
<div id="g-_ai-chart-box" bind:clientWidth="{width}">
|
<div id="g-_ai-chart-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: xs -->
|
<!-- Artboard: xs -->
|
||||||
{#if width && width >= 0 && width < 510}
|
{#if width && width >= 0 && width < 510}
|
||||||
<div id="g-_ai-chart-xs" class="g-artboard" style="">
|
<div id="g-_ai-chart-xs" class="g-artboard" style="">
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
id="g-_ai-chart-xs-img"
|
id="g-_ai-chart-xs-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartXs});`}"
|
style={`background-image: url(${chartXs});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai0-1"
|
id="g-ai0-1"
|
||||||
|
|
@ -159,7 +159,7 @@
|
||||||
id="g-_ai-chart-sm-img"
|
id="g-_ai-chart-sm-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartSm});`}"
|
style={`background-image: url(${chartSm});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai1-1"
|
id="g-ai1-1"
|
||||||
|
|
@ -292,7 +292,7 @@
|
||||||
id="g-_ai-chart-md-img"
|
id="g-_ai-chart-md-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartMd});`}"
|
style={`background-image: url(${chartMd});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai2-1"
|
id="g-ai2-1"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
import Map from './stories/graphic.svelte';
|
import Map from './stories/graphic.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Headline {...args} />
|
<Headline {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -52,49 +52,49 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
section: 'World News',
|
section: 'World News',
|
||||||
hed: 'Reuters Graphics interactive',
|
hed: 'Reuters Graphics interactive',
|
||||||
hedSize: 'normal',
|
hedSize: 'normal',
|
||||||
dek: '',
|
dek: '',
|
||||||
authors: [],
|
authors: [],
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="With dek" {...withStoryDocs(withDekDocs)}>
|
<Story name="With dek" {...withStoryDocs(withDekDocs)}>
|
||||||
<Headline
|
<Headline
|
||||||
hed="{'Reuters Graphics Interactive'}"
|
hed={'Reuters Graphics Interactive'}
|
||||||
dek="{'The beginning of a beautiful page'}"
|
dek={'The beginning of a beautiful page'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
/>
|
/>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
<Story name="With byline" {...withStoryDocs(withBylineDocs)}>
|
<Story name="With byline" {...withStoryDocs(withBylineDocs)}>
|
||||||
<Headline
|
<Headline
|
||||||
hed="{'Reuters Graphics Interactive'}"
|
hed={'Reuters Graphics Interactive'}
|
||||||
dek="{'The beginning of a beautiful page'}"
|
dek={'The beginning of a beautiful page'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
authors="{['Dea Bankova', 'Aditi Bhandari']}"
|
authors={['Dea Bankova', 'Aditi Bhandari']}
|
||||||
publishTime="{new Date('2020-01-01').toISOString()}"
|
publishTime={new Date('2020-01-01').toISOString()}
|
||||||
/>
|
/>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
<Story name="With custom hed" {...withStoryDocs(customHedDocs)}>
|
<Story name="With custom hed" {...withStoryDocs(customHedDocs)}>
|
||||||
<Headline width="wide">
|
<Headline width="wide">
|
||||||
{#snippet hed()}
|
{#snippet hed()}
|
||||||
<h1 class="custom-hed" >
|
<h1 class="custom-hed">
|
||||||
<span class="small block text-base">The secret to</span>
|
<span class="small block text-base">The secret to</span>
|
||||||
“The Nutcracker's”
|
“The Nutcracker's”
|
||||||
<span class="small block text-base fpt-1">success</span>
|
<span class="small block text-base fpt-1">success</span>
|
||||||
</h1>
|
</h1>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet dek()}
|
{#snippet dek()}
|
||||||
<p class="custom-dek !fmt-3" >
|
<p class="custom-dek !fmt-3">
|
||||||
How “The Nutcracker” ballet became an<span
|
How “The Nutcracker” ballet became an<span
|
||||||
class="font-medium mx-1 px-1.5 py-1">American holday staple</span
|
class="font-medium mx-1 px-1.5 py-1">American holday staple</span
|
||||||
>and a financial pillar of ballet companies across the country
|
>and a financial pillar of ballet companies across the country
|
||||||
</p>
|
</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Headline>
|
</Headline>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.custom-hed {
|
.custom-hed {
|
||||||
|
|
@ -109,21 +109,20 @@
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
<Story name="With crown image" {...withStoryDocs(withCrownImgDocs)}>
|
<Story name="With crown image" {...withStoryDocs(withCrownImgDocs)}>
|
||||||
<Headline class="!fmt-3" publishTime="{new Date('2020-01-01').toISOString()}">
|
<Headline class="!fmt-3" publishTime={new Date('2020-01-01').toISOString()}>
|
||||||
<!-- Add a crown -->
|
<!-- Add a crown -->
|
||||||
{#snippet crown()}
|
{#snippet crown()}
|
||||||
<img
|
<img
|
||||||
|
src={crownImgSrc}
|
||||||
src="{crownImgSrc}"
|
|
||||||
width="100"
|
width="100"
|
||||||
class="mx-auto mb-0"
|
class="mx-auto mb-0"
|
||||||
alt="Illustration of Europe"
|
alt="Illustration of Europe"
|
||||||
/>
|
/>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
<!-- Override the hed with a named slot -->
|
<!-- Override the hed with a named slot -->
|
||||||
{#snippet hed()}
|
{#snippet hed()}
|
||||||
<h1 class="!font-serif !tracking-wide">Europa</h1>
|
<h1 class="!font-serif !tracking-wide">Europa</h1>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Headline>
|
</Headline>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
|
|
@ -131,17 +130,17 @@
|
||||||
<Headline
|
<Headline
|
||||||
width="wider"
|
width="wider"
|
||||||
class="!fmt-1"
|
class="!fmt-1"
|
||||||
hed="{'Unfriendly skies'}"
|
hed={'Unfriendly skies'}
|
||||||
dek="{'How Russia’s invasion of Ukraine is redrawing air routes'}"
|
dek={'How Russia’s invasion of Ukraine is redrawing air routes'}
|
||||||
section="{'Ukraine Crisis'}"
|
section={'Ukraine Crisis'}
|
||||||
authors="{['Simon Scarr', 'Vijdan Mohammad Kawoosa']}"
|
authors={['Simon Scarr', 'Vijdan Mohammad Kawoosa']}
|
||||||
publishTime="{new Date('2022-03-04').toISOString()}"
|
publishTime={new Date('2022-03-04').toISOString()}
|
||||||
>
|
>
|
||||||
<!-- Add a crown graphic -->
|
<!-- Add a crown graphic -->
|
||||||
{#snippet crown()}
|
{#snippet crown()}
|
||||||
<div >
|
<div>
|
||||||
<Map />
|
<Map />
|
||||||
</div>
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Headline>
|
</Headline>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,8 @@
|
||||||
<!-- Headline named slot -->
|
<!-- Headline named slot -->
|
||||||
<slot name="hed" />
|
<slot name="hed" />
|
||||||
{:else}
|
{:else}
|
||||||
<h1 class="{hedClass}">
|
<h1 class={hedClass}>
|
||||||
<Markdown source="{hed}" parseInline />
|
<Markdown source={hed} parseInline />
|
||||||
</h1>
|
</h1>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $$slots.dek}
|
{#if $$slots.dek}
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
</div>
|
</div>
|
||||||
{:else if dek}
|
{:else if dek}
|
||||||
<div class="dek fmx-auto fmb-6">
|
<div class="dek fmx-auto fmb-6">
|
||||||
<Markdown source="{dek}" />
|
<Markdown source={dek} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
let width = $state(null);
|
let width = $state(null);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="g-graphic-box" bind:clientWidth="{width}">
|
<div id="g-graphic-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: xs -->
|
<!-- Artboard: xs -->
|
||||||
{#if width && width >= 0 && width < 510}
|
{#if width && width >= 0 && width < 510}
|
||||||
<div id="g-graphic-xs" class="g-artboard" style="">
|
<div id="g-graphic-xs" class="g-artboard" style="">
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-graphic-xs-img"
|
id="g-graphic-xs-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartXs});`}"
|
style={`background-image: url(${chartXs});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai0-3"
|
id="g-ai0-3"
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-graphic-sm-img"
|
id="g-graphic-sm-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartSm});`}"
|
style={`background-image: url(${chartSm});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai1-1"
|
id="g-ai1-1"
|
||||||
|
|
@ -213,7 +213,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-graphic-md-img"
|
id="g-graphic-md-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartMd});`}"
|
style={`background-image: url(${chartMd});`}
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -346,7 +346,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-graphic-lg-img"
|
id="g-graphic-lg-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartLg});`}"
|
style={`background-image: url(${chartLg});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai3-1"
|
id="g-ai3-1"
|
||||||
|
|
@ -485,7 +485,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-graphic-xl-img"
|
id="g-graphic-xl-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartXl});`}"
|
style={`background-image: url(${chartXl});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai4-1"
|
id="g-ai4-1"
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,14 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="With backdrop photo"
|
name="With backdrop photo"
|
||||||
args="{{
|
args={{
|
||||||
section: 'World News',
|
section: 'World News',
|
||||||
hed: 'Reuters Graphics Interactive',
|
hed: 'Reuters Graphics Interactive',
|
||||||
dek: 'The beginning of a beautiful page',
|
dek: 'The beginning of a beautiful page',
|
||||||
authors: ['Simon Scarr', 'Vijdan Mohammad Kawoosa'],
|
authors: ['Simon Scarr', 'Vijdan Mohammad Kawoosa'],
|
||||||
publishTime: new Date('2022-03-04').toISOString(),
|
publishTime: new Date('2022-03-04').toISOString(),
|
||||||
img: polarImgSrc,
|
img: polarImgSrc,
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="With transparent header" {...withStoryDocs(transparentHeaderDocs)}>
|
<Story name="With transparent header" {...withStoryDocs(transparentHeaderDocs)}>
|
||||||
|
|
@ -95,9 +95,9 @@
|
||||||
section="World News"
|
section="World News"
|
||||||
hed="Reuters Graphics Interactive"
|
hed="Reuters Graphics Interactive"
|
||||||
dek="The beginning of a beautiful page"
|
dek="The beginning of a beautiful page"
|
||||||
authors="{['Simon Scarr', 'Vijdan Mohammad Kawoosa']}"
|
authors={['Simon Scarr', 'Vijdan Mohammad Kawoosa']}
|
||||||
publishTime="{new Date('2022-03-04').toISOString()}"
|
publishTime={new Date('2022-03-04').toISOString()}
|
||||||
img="{polarImgSrc}"
|
img={polarImgSrc}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
@ -108,12 +108,12 @@
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<HeroHeadline
|
<HeroHeadline
|
||||||
hed="{'Earthquake devastates Afghanistan'}"
|
hed={'Earthquake devastates Afghanistan'}
|
||||||
hedSize="{'big'}"
|
hedSize={'big'}
|
||||||
hedWidth="wide"
|
hedWidth="wide"
|
||||||
class="custom-hero mb-0"
|
class="custom-hero mb-0"
|
||||||
dek=""
|
dek=""
|
||||||
authors="{[
|
authors={[
|
||||||
'Anand Katakam',
|
'Anand Katakam',
|
||||||
'Vijdan Mohammad Kawoosa',
|
'Vijdan Mohammad Kawoosa',
|
||||||
'Adolfo Arranz',
|
'Adolfo Arranz',
|
||||||
|
|
@ -123,8 +123,8 @@
|
||||||
'Jitesh Chowdhury',
|
'Jitesh Chowdhury',
|
||||||
'Manas Sharma',
|
'Manas Sharma',
|
||||||
'Aditi Bhandari',
|
'Aditi Bhandari',
|
||||||
]}"
|
]}
|
||||||
publishTime="{new Date('2022-06-24').toISOString()}"
|
publishTime={new Date('2022-06-24').toISOString()}
|
||||||
>
|
>
|
||||||
<div slot="background">
|
<div slot="background">
|
||||||
<GraphicBlock
|
<GraphicBlock
|
||||||
|
|
@ -135,7 +135,7 @@
|
||||||
notes=""
|
notes=""
|
||||||
ariaDescription="Earthquake impact map"
|
ariaDescription="Earthquake impact map"
|
||||||
>
|
>
|
||||||
<svelte:component this="{QuakeMap}" />
|
<svelte:component this={QuakeMap} />
|
||||||
</GraphicBlock>
|
</GraphicBlock>
|
||||||
</div>
|
</div>
|
||||||
</HeroHeadline>
|
</HeroHeadline>
|
||||||
|
|
@ -186,16 +186,16 @@
|
||||||
hed="The conflict in Ethiopia"
|
hed="The conflict in Ethiopia"
|
||||||
hedSize="bigger"
|
hedSize="bigger"
|
||||||
hedWidth="wide"
|
hedWidth="wide"
|
||||||
authors="{['Aditi Bhandari ', 'David Lewis']}"
|
authors={['Aditi Bhandari ', 'David Lewis']}
|
||||||
publishTime="{new Date('2020-12-18').toISOString()}"
|
publishTime={new Date('2020-12-18').toISOString()}
|
||||||
>
|
>
|
||||||
<div slot="background">
|
<div slot="background">
|
||||||
<Video
|
<Video
|
||||||
width="widest"
|
width="widest"
|
||||||
class="my-0"
|
class="my-0"
|
||||||
showControls="{false}"
|
showControls={false}
|
||||||
preloadVideo="auto"
|
preloadVideo="auto"
|
||||||
playVideoWhenInView="{false}"
|
playVideoWhenInView={false}
|
||||||
src="https://vm.reuters.tv/9c72e/titlef2ac(425954_R21MP41500).mp4"
|
src="https://vm.reuters.tv/9c72e/titlef2ac(425954_R21MP41500).mp4"
|
||||||
poster="https://www.reuters.com/resizer/vexYmtEuXKmfnsCbfS6jSMVbHms=/1080x0/filters:quality(80)/cloudfront-us-east-2.images.arcpublishing.com/reuters/VKJHKJEENVO4DASDND3VLHPV5Y.jpg"
|
poster="https://www.reuters.com/resizer/vexYmtEuXKmfnsCbfS6jSMVbHms=/1080x0/filters:quality(80)/cloudfront-us-east-2.images.arcpublishing.com/reuters/VKJHKJEENVO4DASDND3VLHPV5Y.jpg"
|
||||||
notes="Drone footage from the Village 8 refugee camp in Sudan."
|
notes="Drone footage from the Village 8 refugee camp in Sudan."
|
||||||
|
|
@ -227,13 +227,13 @@
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<HeroHeadline
|
<HeroHeadline
|
||||||
hed="{'Buried under the bricks'}"
|
hed={'Buried under the bricks'}
|
||||||
hedWidth="wide"
|
hedWidth="wide"
|
||||||
class="mb-0"
|
class="mb-0"
|
||||||
dek="{'How mud-brick housing made the Morocco earthquake so deadly'}"
|
dek={'How mud-brick housing made the Morocco earthquake so deadly'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
authors="{['Mariano Zafra']}"
|
authors={['Mariano Zafra']}
|
||||||
publishTime="{new Date('2020-01-01').toISOString()}"
|
publishTime={new Date('2020-01-01').toISOString()}
|
||||||
>
|
>
|
||||||
<div slot="inline">
|
<div slot="inline">
|
||||||
<FeaturePhoto
|
<FeaturePhoto
|
||||||
|
|
@ -253,13 +253,13 @@
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<HeroHeadline
|
<HeroHeadline
|
||||||
hed="{'The plunge from 29,000 feet'}"
|
hed={'The plunge from 29,000 feet'}
|
||||||
hedWidth="wide"
|
hedWidth="wide"
|
||||||
class="mb-0"
|
class="mb-0"
|
||||||
dek="{'How China Eastern Airlines flight MU5735 went from an uneventful flight at cruising altitude to disaster in just minutes.'}"
|
dek={'How China Eastern Airlines flight MU5735 went from an uneventful flight at cruising altitude to disaster in just minutes.'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
authors="{['Simon Scarr', 'Vijdan Mohammad Kawoosa']}"
|
authors={['Simon Scarr', 'Vijdan Mohammad Kawoosa']}
|
||||||
publishTime="{new Date('2020-01-01').toISOString()}"
|
publishTime={new Date('2020-01-01').toISOString()}
|
||||||
>
|
>
|
||||||
<div slot="inline">
|
<div slot="inline">
|
||||||
<GraphicBlock
|
<GraphicBlock
|
||||||
|
|
@ -270,7 +270,7 @@
|
||||||
notes="Source: Satellite image from Google, Maxar Technologies, CNES/Airbus, Landsat/Copernicus"
|
notes="Source: Satellite image from Google, Maxar Technologies, CNES/Airbus, Landsat/Copernicus"
|
||||||
ariaDescription="Aerial map showing trajectory of crash"
|
ariaDescription="Aerial map showing trajectory of crash"
|
||||||
>
|
>
|
||||||
<svelte:component this="{CrashMap}" />
|
<svelte:component this={CrashMap} />
|
||||||
</GraphicBlock>
|
</GraphicBlock>
|
||||||
</div>
|
</div>
|
||||||
</HeroHeadline>
|
</HeroHeadline>
|
||||||
|
|
@ -282,21 +282,21 @@
|
||||||
</Block>
|
</Block>
|
||||||
|
|
||||||
<HeroHeadline
|
<HeroHeadline
|
||||||
hed="{'Devastation in Derna'}"
|
hed={'Devastation in Derna'}
|
||||||
hedWidth="wide"
|
hedWidth="wide"
|
||||||
class="mb-0"
|
class="mb-0"
|
||||||
dek="{'How raging floods burst dams, destroyed neighbourhoods and killed thousands in Libya'}"
|
dek={'How raging floods burst dams, destroyed neighbourhoods and killed thousands in Libya'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
authors="{['Simon Scarr']}"
|
authors={['Simon Scarr']}
|
||||||
publishTime="{new Date('2020-01-01').toISOString()}"
|
publishTime={new Date('2020-01-01').toISOString()}
|
||||||
>
|
>
|
||||||
<div slot="inline">
|
<div slot="inline">
|
||||||
<Video
|
<Video
|
||||||
width="widest"
|
width="widest"
|
||||||
class="my-0"
|
class="my-0"
|
||||||
showControls="{false}"
|
showControls={false}
|
||||||
preloadVideo="auto"
|
preloadVideo="auto"
|
||||||
playVideoWhenInView="{false}"
|
playVideoWhenInView={false}
|
||||||
src="https://www.reuters.com/graphics/LIBYA-STORM/EXPLAINER/klvyzqebzpg/cdn/video/drone.mp4"
|
src="https://www.reuters.com/graphics/LIBYA-STORM/EXPLAINER/klvyzqebzpg/cdn/video/drone.mp4"
|
||||||
notes="Drone shots of Derna, Libya. September 14, 2023. REUTERS"
|
notes="Drone shots of Derna, Libya. September 14, 2023. REUTERS"
|
||||||
ariaDescription="alttext fot video"
|
ariaDescription="alttext fot video"
|
||||||
|
|
@ -308,14 +308,14 @@
|
||||||
<Story name="With custom hed" {...withStoryDocs(customHedDocs)}>
|
<Story name="With custom hed" {...withStoryDocs(customHedDocs)}>
|
||||||
<HeroHeadline
|
<HeroHeadline
|
||||||
class="custom-hed"
|
class="custom-hed"
|
||||||
authors="{[
|
authors={[
|
||||||
'Prasanta Kumar Dutta',
|
'Prasanta Kumar Dutta',
|
||||||
'Dea Bankova',
|
'Dea Bankova',
|
||||||
'Aditi Bhandari',
|
'Aditi Bhandari',
|
||||||
'Anurag Rao',
|
'Anurag Rao',
|
||||||
]}"
|
]}
|
||||||
publishTime="{new Date('2023-05-11').toISOString()}"
|
publishTime={new Date('2023-05-11').toISOString()}
|
||||||
img="{eurovisImgSrc}"
|
img={eurovisImgSrc}
|
||||||
>
|
>
|
||||||
<h1 slot="hed">
|
<h1 slot="hed">
|
||||||
<div class="body-note">A visual guide to</div>
|
<div class="body-note">A visual guide to</div>
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@
|
||||||
{#if $$slots.hed}
|
{#if $$slots.hed}
|
||||||
<Headline
|
<Headline
|
||||||
class="{cls} !text-{hedAlign}"
|
class="{cls} !text-{hedAlign}"
|
||||||
width="{hedWidth}"
|
width={hedWidth}
|
||||||
{section}
|
{section}
|
||||||
{hedSize}
|
{hedSize}
|
||||||
{hed}
|
{hed}
|
||||||
|
|
@ -110,7 +110,7 @@
|
||||||
{:else}
|
{:else}
|
||||||
<Headline
|
<Headline
|
||||||
class="{cls} !text-{hedAlign}"
|
class="{cls} !text-{hedAlign}"
|
||||||
width="{hedWidth}"
|
width={hedWidth}
|
||||||
{section}
|
{section}
|
||||||
{hedSize}
|
{hedSize}
|
||||||
{hed}
|
{hed}
|
||||||
|
|
@ -144,11 +144,11 @@
|
||||||
<!-- Inline hero -->
|
<!-- Inline hero -->
|
||||||
{#if $$slots.inline}
|
{#if $$slots.inline}
|
||||||
<Block width="fluid" class="hero-headline inline-hero">
|
<Block width="fluid" class="hero-headline inline-hero">
|
||||||
<PaddingReset containerIsFluid="{true}">
|
<PaddingReset containerIsFluid={true}>
|
||||||
{#if $$slots.hed}
|
{#if $$slots.hed}
|
||||||
<Headline
|
<Headline
|
||||||
class="{cls} !text-{hedAlign}"
|
class="{cls} !text-{hedAlign}"
|
||||||
width="{hedWidth}"
|
width={hedWidth}
|
||||||
{section}
|
{section}
|
||||||
{hedSize}
|
{hedSize}
|
||||||
{hed}
|
{hed}
|
||||||
|
|
@ -162,7 +162,7 @@
|
||||||
{:else}
|
{:else}
|
||||||
<Headline
|
<Headline
|
||||||
class="{cls} !text-{hedAlign}"
|
class="{cls} !text-{hedAlign}"
|
||||||
width="{hedWidth}"
|
width={hedWidth}
|
||||||
{section}
|
{section}
|
||||||
{hedSize}
|
{hedSize}
|
||||||
{hed}
|
{hed}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
<!-- Generated by ai2html v0.100.0 - 2022-03-29 17:01 -->
|
<!-- Generated by ai2html v0.100.0 - 2022-03-29 17:01 -->
|
||||||
|
|
||||||
<div id="g-CRASH_1-box" bind:clientWidth="{width}">
|
<div id="g-CRASH_1-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: xs -->
|
<!-- Artboard: xs -->
|
||||||
{#if width && width >= 0 && width < 510}
|
{#if width && width >= 0 && width < 510}
|
||||||
<div id="g-CRASH_1-xs" class="g-artboard" style="">
|
<div id="g-CRASH_1-xs" class="g-artboard" style="">
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
id="g-CRASH_1-xs-img"
|
id="g-CRASH_1-xs-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartXs});`}"
|
style={`background-image: url(${chartXs});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai0-1"
|
id="g-ai0-1"
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
id="g-CRASH_1-sm-img"
|
id="g-CRASH_1-sm-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartSm});`}"
|
style={`background-image: url(${chartSm});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai1-1"
|
id="g-ai1-1"
|
||||||
|
|
@ -133,7 +133,7 @@
|
||||||
id="g-CRASH_1-md-img"
|
id="g-CRASH_1-md-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartMd});`}"
|
style={`background-image: url(${chartMd});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai2-1"
|
id="g-ai2-1"
|
||||||
|
|
@ -194,7 +194,7 @@
|
||||||
id="g-CRASH_1-lg-img"
|
id="g-CRASH_1-lg-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartLg});`}"
|
style={`background-image: url(${chartLg});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai3-1"
|
id="g-ai3-1"
|
||||||
|
|
@ -255,7 +255,7 @@
|
||||||
id="g-CRASH_1-xl-img"
|
id="g-CRASH_1-xl-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartXl});`}"
|
style={`background-image: url(${chartXl});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai4-1"
|
id="g-ai4-1"
|
||||||
|
|
@ -316,7 +316,7 @@
|
||||||
id="g-CRASH_1-xl_copy-img"
|
id="g-CRASH_1-xl_copy-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
alt=""
|
alt=""
|
||||||
style="{`background-image: url(${chartXxl});`}"
|
style={`background-image: url(${chartXxl});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai5-1"
|
id="g-ai5-1"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
import chartXl from '././quake-map-top-xl.jpeg';
|
import chartXl from '././quake-map-top-xl.jpeg';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="g-quake-map-top-box" bind:clientWidth="{width}">
|
<div id="g-quake-map-top-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: xs -->
|
<!-- Artboard: xs -->
|
||||||
{#if width && width >= 0 && width < 510}
|
{#if width && width >= 0 && width < 510}
|
||||||
<div id="g-quake-map-top-xs" class="g-artboard" style="">
|
<div id="g-quake-map-top-xs" class="g-artboard" style="">
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-quake-map-top-xs-img"
|
id="g-quake-map-top-xs-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartXs});`}"
|
style={`background-image: url(${chartXs});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai0-1"
|
id="g-ai0-1"
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-quake-map-top-sm-img"
|
id="g-quake-map-top-sm-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartSm});`}"
|
style={`background-image: url(${chartSm});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai1-1"
|
id="g-ai1-1"
|
||||||
|
|
@ -183,7 +183,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-quake-map-top-md-img"
|
id="g-quake-map-top-md-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartMd});`}"
|
style={`background-image: url(${chartMd});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai2-1"
|
id="g-ai2-1"
|
||||||
|
|
@ -271,7 +271,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-quake-map-top-lg-img"
|
id="g-quake-map-top-lg-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartLg});`}"
|
style={`background-image: url(${chartLg});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai3-1"
|
id="g-ai3-1"
|
||||||
|
|
@ -359,7 +359,7 @@
|
||||||
<div
|
<div
|
||||||
id="g-quake-map-top-xl-img"
|
id="g-quake-map-top-xl-img"
|
||||||
class="g-aiImg"
|
class="g-aiImg"
|
||||||
style="{`background-image: url(${chartXl});`}"
|
style={`background-image: url(${chartXl});`}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
id="g-ai4-1"
|
id="g-ai4-1"
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
const photos = photosJson.map((p) => ({ ...p, altText: p.caption }));
|
const photos = photosJson.map((p) => ({ ...p, altText: p.caption }));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<PhotoCarousel {...args} />
|
<PhotoCarousel {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -37,18 +37,18 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'wider',
|
width: 'wider',
|
||||||
photos,
|
photos,
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Custom credits and captions"
|
name="Custom credits and captions"
|
||||||
args="{{
|
args={{
|
||||||
width: 'wider',
|
width: 'wider',
|
||||||
photos,
|
photos,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(customDocs)}
|
{...withStoryDocs(customDocs)}
|
||||||
>
|
>
|
||||||
<PhotoCarousel
|
<PhotoCarousel
|
||||||
|
|
@ -58,11 +58,11 @@
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#snippet credit({ credit })}
|
{#snippet credit({ credit })}
|
||||||
<p class="custom-credit" >{credit}</p>
|
<p class="custom-credit">{credit}</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet caption({ caption })}
|
{#snippet caption({ caption })}
|
||||||
<p class="custom-caption" >{caption}</p>
|
<p class="custom-caption">{caption}</p>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</PhotoCarousel>
|
</PhotoCarousel>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,17 +111,17 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Block {width} {id} class="photo-carousel fmy-6 {cls}">
|
<Block {width} {id} class="photo-carousel fmy-6 {cls}">
|
||||||
<div class="carousel-container" bind:clientWidth="{containerWidth}">
|
<div class="carousel-container" bind:clientWidth={containerWidth}>
|
||||||
<Splide
|
<Splide
|
||||||
hasTrack="{false}"
|
hasTrack={false}
|
||||||
options="{{
|
options={{
|
||||||
height: carouselHeight,
|
height: carouselHeight,
|
||||||
fixedHeight: carouselHeight,
|
fixedHeight: carouselHeight,
|
||||||
lazyLoad: 'nearby',
|
lazyLoad: 'nearby',
|
||||||
preloadPages: preloadImages,
|
preloadPages: preloadImages,
|
||||||
}}"
|
}}
|
||||||
aria-label="{carouselAriaLabel}"
|
aria-label={carouselAriaLabel}
|
||||||
on:move="{handleActiveChange}"
|
on:move={handleActiveChange}
|
||||||
>
|
>
|
||||||
<div class="image-container">
|
<div class="image-container">
|
||||||
<SplideTrack>
|
<SplideTrack>
|
||||||
|
|
@ -134,20 +134,19 @@
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="w-full h-full fmy-0"
|
class="w-full h-full fmy-0"
|
||||||
data-splide-lazy="{photo.src}"
|
data-splide-lazy={photo.src}
|
||||||
alt="{photo.altText}"
|
alt={photo.altText}
|
||||||
style:object-fit="{photo.objectFit ||
|
style:object-fit={photo.objectFit || defaultImageObjectFit}
|
||||||
defaultImageObjectFit}"
|
style:object-position={photo.objectPosition ||
|
||||||
style:object-position="{photo.objectPosition ||
|
defaultImageObjectPosition}
|
||||||
defaultImageObjectPosition}"
|
|
||||||
/>
|
/>
|
||||||
{#if $$slots.credit}
|
{#if $$slots.credit}
|
||||||
<slot name="credit" credit="{photo.credit}" />
|
<slot name="credit" credit={photo.credit} />
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="credit absolute fmb-1 fml-1 leading-tighter font-note text-xxs"
|
class="credit absolute fmb-1 fml-1 leading-tighter font-note text-xxs"
|
||||||
class:contain-fit="{photo.objectFit === 'contain' ||
|
class:contain-fit={photo.objectFit === 'contain' ||
|
||||||
defaultImageObjectFit === 'contain'}"
|
defaultImageObjectFit === 'contain'}
|
||||||
>{photo.credit}</span
|
>{photo.credit}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -158,18 +157,18 @@
|
||||||
</SplideTrack>
|
</SplideTrack>
|
||||||
|
|
||||||
{#if photos[activeImageIndex].caption}
|
{#if photos[activeImageIndex].caption}
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<Block width="{textWidth}">
|
<Block width={textWidth}>
|
||||||
{#if $$slots.caption}
|
{#if $$slots.caption}
|
||||||
<slot
|
<slot
|
||||||
name="caption"
|
name="caption"
|
||||||
caption="{photos[activeImageIndex].caption}"
|
caption={photos[activeImageIndex].caption}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
{#key activeImageIndex}
|
{#key activeImageIndex}
|
||||||
<p
|
<p
|
||||||
class="caption body-caption text-center"
|
class="caption body-caption text-center"
|
||||||
in:fly|local="{{ x: 20, duration: 175 }}"
|
in:fly|local={{ x: 20, duration: 175 }}
|
||||||
>
|
>
|
||||||
{photos[activeImageIndex].caption}
|
{photos[activeImageIndex].caption}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -185,10 +184,10 @@
|
||||||
|
|
||||||
<div class="splide__arrows fp-1">
|
<div class="splide__arrows fp-1">
|
||||||
<button class="splide__arrow splide__arrow--prev">
|
<button class="splide__arrow splide__arrow--prev">
|
||||||
<Fa icon="{faChevronLeft}" fw />
|
<Fa icon={faChevronLeft} fw />
|
||||||
</button>
|
</button>
|
||||||
<button class="splide__arrow splide__arrow--next">
|
<button class="splide__arrow splide__arrow--next">
|
||||||
<Fa icon="{faChevronRight}" fw />
|
<Fa icon={faChevronRight} fw />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
127
src/components/PhotoPack/PhotoPack.mdx
Normal file
127
src/components/PhotoPack/PhotoPack.mdx
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
import { Meta, Canvas } from '@storybook/blocks';
|
||||||
|
|
||||||
|
import * as PhotoPackStories from './PhotoPack.stories.svelte';
|
||||||
|
|
||||||
|
<Meta of={PhotoPackStories} />
|
||||||
|
|
||||||
|
# PhotoPack
|
||||||
|
|
||||||
|
The `PhotoPack` component makes simple photo grids with custom layouts at various breakpoints.
|
||||||
|
|
||||||
|
`images` are defined with their src, alt text, captions and an optional `maxHeight`, which ensures that the images are no taller than that height in any layout.
|
||||||
|
|
||||||
|
`layouts` describe how images will be laid out at different breakpoints. The default layout is one photo per row, stacked vertically -- i.e. mobile layout. You can customise the layouts and group images into `rows` above a certain `breakpoint` by specifying the number of images that should go in that row. For example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const layouts = [
|
||||||
|
{
|
||||||
|
breakpoint: 450,
|
||||||
|
rows: [1, 2, 1],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
```
|
||||||
|
|
||||||
|
... tells the component that when the `PhotoPack` container is 450 pixels or wider, it should group the 4 images in 3 rows: 1 in the first, 2 in the second and 1 in the last.
|
||||||
|
|
||||||
|
You can define as many layouts for as many images as you like.
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<script>
|
||||||
|
import { PhotoPack } from '@reuters-graphics/graphics-components';
|
||||||
|
|
||||||
|
/** Array of photo metadata */
|
||||||
|
const images = [
|
||||||
|
{
|
||||||
|
src: 'https://...',
|
||||||
|
altText: 'Alt text',
|
||||||
|
caption: 'Lorem ipsum. REUTERS/Photog',
|
||||||
|
// Optional max-height of images across all layouts
|
||||||
|
maxHeight: 800,
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
];
|
||||||
|
|
||||||
|
/** Set the number of photos in each row at various breakpoints */
|
||||||
|
const layouts = [
|
||||||
|
{
|
||||||
|
breakpoint: 450, // Applies to containers wider than 450px
|
||||||
|
rows: [1, 2, 1], // Number of photos in each row
|
||||||
|
},
|
||||||
|
// Another layout for containers wider than 750px
|
||||||
|
{ breakpoint: 750, rows: [1, 3] },
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<PhotoPack {images} {layouts} />
|
||||||
|
```
|
||||||
|
|
||||||
|
<Canvas of={PhotoPackStories.Demo} />
|
||||||
|
|
||||||
|
## ArchieML
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
[blocks]
|
||||||
|
# ...
|
||||||
|
|
||||||
|
type: photo-pack
|
||||||
|
id: my-photo-pack
|
||||||
|
class: mb-2
|
||||||
|
width: wide
|
||||||
|
textWidth: normal
|
||||||
|
gap: 10
|
||||||
|
[.images]
|
||||||
|
src: images/my-img-1.jpg
|
||||||
|
altText: Alt text
|
||||||
|
caption: Lorem ipsum. REUTERS/Photog
|
||||||
|
|
||||||
|
src: images/my-img-2.jpg
|
||||||
|
altText: Alt text
|
||||||
|
caption: Lorem ipsum. REUTERS/Photog
|
||||||
|
|
||||||
|
src: images/my-img-3.jpg
|
||||||
|
altText: Alt text
|
||||||
|
caption: Lorem ipsum. REUTERS/Photog
|
||||||
|
|
||||||
|
src: images/my-img-4.jpg
|
||||||
|
altText: Alt text
|
||||||
|
caption: Lorem ipsum. REUTERS/Photog
|
||||||
|
|
||||||
|
src: images/my-img-5.jpg
|
||||||
|
altText: Alt text
|
||||||
|
caption: Lorem ipsum. REUTERS/Photog
|
||||||
|
[]
|
||||||
|
|
||||||
|
# ...
|
||||||
|
[]
|
||||||
|
```
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<!-- App.svelte -->
|
||||||
|
{#each content.blocks as block}
|
||||||
|
{#if block.type === 'text'}
|
||||||
|
<!-- ... -->
|
||||||
|
{:else if block.type === 'photo-pack'}
|
||||||
|
<PhotoPack
|
||||||
|
id={block.id}
|
||||||
|
class={block.class}
|
||||||
|
width={block.width}
|
||||||
|
textWidth={block.textWidth}
|
||||||
|
images={block.images.map((img) => ({
|
||||||
|
src: `${assets}/${img.src}`,
|
||||||
|
altText: img.altText,
|
||||||
|
caption: img.caption,
|
||||||
|
}))}
|
||||||
|
layouts={[
|
||||||
|
{ breakpoint: 750, rows: [2, 3] },
|
||||||
|
{ breakpoint: 450, rows: [1, 2, 2] },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- ... -->
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Misisng alt text
|
||||||
|
|
||||||
|
If any of your images is missing `altText` a small warning will overlay the photo.
|
||||||
|
|
@ -1,19 +1,10 @@
|
||||||
<script module lang="ts">
|
<script module lang="ts">
|
||||||
// @ts-ignore raw
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||||
import componentDocs from './stories/docs/component.md?raw';
|
|
||||||
// @ts-ignore raw
|
|
||||||
import archieMLDocs from './stories/docs/archieML.md?raw';
|
|
||||||
// @ts-ignore raw
|
|
||||||
import missingAltTextDocs from './stories/docs/missingAltText.md?raw';
|
|
||||||
|
|
||||||
import PhotoPack from './PhotoPack.svelte';
|
import PhotoPack from './PhotoPack.svelte';
|
||||||
|
|
||||||
import { withComponentDocs, withStoryDocs } from '$docs/utils/withParams.js';
|
const { Story } = defineMeta({
|
||||||
|
|
||||||
export const meta = {
|
|
||||||
title: 'Components/Multimedia/PhotoPack',
|
title: 'Components/Multimedia/PhotoPack',
|
||||||
component: PhotoPack,
|
component: PhotoPack,
|
||||||
...withComponentDocs(componentDocs),
|
|
||||||
argTypes: {
|
argTypes: {
|
||||||
width: {
|
width: {
|
||||||
control: 'select',
|
control: 'select',
|
||||||
|
|
@ -24,37 +15,34 @@
|
||||||
options: ['normal', 'wide', 'wider', 'widest', 'fluid'],
|
options: ['normal', 'wide', 'wider', 'widest', 'fluid'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
|
||||||
|
|
||||||
const defaultImages = [
|
const defaultImages = [
|
||||||
{
|
{
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
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',
|
||||||
altText: 'alt text',
|
|
||||||
caption:
|
caption:
|
||||||
'A residential building destroyed by shelling in the settlement of Borodyanka in the Kyiv region, Ukraine March 3, 2022. Picture taken with a drone. REUTERS/Maksim Levin',
|
"Spain's Sergio Busquets and Aymeric Laporte react before a Germany goal is disallowed following a VAR review.",
|
||||||
maxHeight: 400,
|
altText: 'alt text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: 'https://via.placeholder.com/1640x1180.jpg',
|
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',
|
||||||
altText: 'alt text',
|
|
||||||
caption:
|
caption:
|
||||||
'Surveillance footage shows a missile hitting a residential building in Kyiv, Ukraine, February 26, 2022, in this still image taken from a video obtained by REUTERS',
|
"Spain's Sergio Busquets fouls Germany's Jamal Musiala before being shown yellow card.",
|
||||||
|
altText: 'alt text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: 'https://via.placeholder.com/1200x900.jpg',
|
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',
|
||||||
altText: 'alt text',
|
|
||||||
caption:
|
caption:
|
||||||
'People walk past the remains of a missile at a bus terminal in Kyiv, Ukraine March 4, 2022. REUTERS/Valentyn Ogirenko',
|
"Spain's Sergio Busquets is shown a yellow card by referee Danny Desmond Makkelie.",
|
||||||
|
altText: 'alt text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
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',
|
||||||
altText: 'alt text',
|
|
||||||
caption:
|
caption:
|
||||||
'People walk past the remains of a missile at a bus terminal. REUTERS/Valentyn Ogirenko',
|
"Spain's Sergio Busquets in action with Germany's Thomas Muller.",
|
||||||
|
altText: 'alt text',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -70,34 +58,7 @@
|
||||||
width: 'wide',
|
width: 'wide',
|
||||||
textWidth: 'normal',
|
textWidth: 'normal',
|
||||||
gap: '15',
|
gap: '15',
|
||||||
images: [
|
images: defaultImages,
|
||||||
{
|
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
|
||||||
caption: 'Lorem ipsum. Reuters/Photog',
|
|
||||||
maxHeight: 600,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
|
||||||
caption: 'Lorem ipsum. Reuters/Photog',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
|
||||||
caption: 'Lorem ipsum. Reuters/Photog',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
|
||||||
caption: 'Lorem ipsum. Reuters/Photog',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
|
||||||
caption: 'Lorem ipsum. Reuters/Photog',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
layouts: [
|
layouts: [
|
||||||
{ breakpoint: 750, rows: [2, 3] },
|
{ breakpoint: 750, rows: [2, 3] },
|
||||||
{ breakpoint: 450, rows: [1, 2, 2] },
|
{ breakpoint: 450, rows: [1, 2, 2] },
|
||||||
|
|
@ -106,8 +67,8 @@
|
||||||
|
|
||||||
const altTextImages = [
|
const altTextImages = [
|
||||||
{
|
{
|
||||||
src: 'https://via.placeholder.com/1024x768.jpg',
|
|
||||||
altText: 'alt text',
|
altText: 'alt text',
|
||||||
|
src: 'https://via.placeholder.com/1024x768.jpg',
|
||||||
caption:
|
caption:
|
||||||
'A residential building destroyed by shelling in the settlement of Borodyanka in the Kyiv region, Ukraine March 3, 2022. Picture taken with a drone. REUTERS/Maksim Levin',
|
'A residential building destroyed by shelling in the settlement of Borodyanka in the Kyiv region, Ukraine March 3, 2022. Picture taken with a drone. REUTERS/Maksim Levin',
|
||||||
maxHeight: 400,
|
maxHeight: 400,
|
||||||
|
|
@ -122,37 +83,23 @@
|
||||||
const altTextLayouts = [{ breakpoint: 450, rows: [2] }];
|
const altTextLayouts = [{ breakpoint: 450, rows: [2] }];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
|
||||||
{#snippet children({ ...args })}
|
|
||||||
<PhotoPack {...args} />
|
|
||||||
{/snippet}
|
|
||||||
</Template>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Demo"
|
||||||
args="{{
|
args={{
|
||||||
width: 'wide',
|
width: 'wide',
|
||||||
textWidth: 'normal',
|
textWidth: 'normal',
|
||||||
images: defaultImages,
|
images: defaultImages,
|
||||||
layouts: defaultLayouts,
|
layouts: defaultLayouts,
|
||||||
}}"
|
}}
|
||||||
/>
|
|
||||||
|
|
||||||
<Story
|
|
||||||
name="ArchieML"
|
|
||||||
{...withStoryDocs(archieMLDocs)}
|
|
||||||
args="{archieMLBlock}"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Missing altText"
|
name="Missing altText"
|
||||||
args="{{
|
exportName="MissingAltText"
|
||||||
|
args={{
|
||||||
width: 'wide',
|
width: 'wide',
|
||||||
textWidth: 'normal',
|
textWidth: 'normal',
|
||||||
images: altTextImages,
|
images: altTextImages,
|
||||||
layouts: altTextLayouts,
|
layouts: altTextLayouts,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(missingAltTextDocs)}
|
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,102 +1,92 @@
|
||||||
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
|
|
||||||
<!-- @component `PhotoPack` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-multimedia-photopack--docs) -->
|
<!-- @component `PhotoPack` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-multimedia-photopack--docs) -->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
interface Image {
|
import Block from '../Block/Block.svelte';
|
||||||
|
import PaddingReset from '../PaddingReset/PaddingReset.svelte';
|
||||||
|
import Markdown from '../Markdown/Markdown.svelte';
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
import { random4 } from '../../utils';
|
||||||
|
import { groupRows } from './utils';
|
||||||
|
// import { groupRows } from './utils';
|
||||||
|
|
||||||
|
// Types
|
||||||
|
export interface Image {
|
||||||
src: string;
|
src: string;
|
||||||
altText: string;
|
altText: string;
|
||||||
caption?: string;
|
caption?: string;
|
||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Array of image objects
|
|
||||||
* @required
|
|
||||||
*/
|
|
||||||
export let images: Image[] = [];
|
|
||||||
|
|
||||||
interface Layout {
|
export interface Layout {
|
||||||
breakpoint: number;
|
breakpoint: number;
|
||||||
rows: number[];
|
rows: number[];
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Array of layout objects
|
|
||||||
* @required
|
|
||||||
*/
|
|
||||||
export let layouts: Layout[] = [];
|
|
||||||
/**
|
|
||||||
* Gap between images.
|
|
||||||
* @type {number}
|
|
||||||
*/
|
|
||||||
export let gap = 15;
|
|
||||||
|
|
||||||
const random4 = () =>
|
|
||||||
Math.floor((1 + Math.random()) * 0x10000)
|
|
||||||
.toString(16)
|
|
||||||
.substring(1);
|
|
||||||
/**
|
|
||||||
* Add an ID to target with SCSS. Should be unique from all other elements.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
export let id: string = 'photopack-' + random4() + random4();
|
|
||||||
/**
|
|
||||||
* Add a class to target with SCSS.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
let cls: string = '';
|
|
||||||
export { cls as class };
|
|
||||||
|
|
||||||
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
|
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
|
||||||
|
|
||||||
/** Width of the component within the text well. */
|
interface Props {
|
||||||
export let width: ContainerWidth = 'normal';
|
/** Array of image objects */
|
||||||
|
images: Image[];
|
||||||
|
/** Array of layout objects */
|
||||||
|
layouts?: Layout[];
|
||||||
|
/** Gap between images. */
|
||||||
|
gap?: number;
|
||||||
|
/** Add an ID to target with SCSS. Should be unique from all other elements. */
|
||||||
|
id?: string;
|
||||||
|
/** Add a class to target with SCSS. */
|
||||||
|
class: string;
|
||||||
|
/** 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. For example, "normal" to keep captions inline with the rest of the text well.
|
||||||
|
*
|
||||||
|
* Can't ever be wider than `width`: 'normal' | 'wide' | 'wider' | 'widest' | 'fluid' */
|
||||||
|
textWidth: ContainerWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
images,
|
||||||
|
layouts,
|
||||||
|
gap = 15,
|
||||||
|
id = 'photopack-' + random4() + random4(),
|
||||||
|
class: cls = '',
|
||||||
|
width = 'normal',
|
||||||
|
textWidth = 'normal',
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
let containerWidth = $state(0); // or undefined?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a different width for captions within the text well, for example,
|
*
|
||||||
* "normal" to keep captions inline with the rest of the text well.
|
* Sort layouts by descending breakpoints.
|
||||||
* Can't ever be wider than `width`.
|
*
|
||||||
* @type {string}
|
* @NOTE - We can't use `sort` directly on the array because it mutates the original array; we can't update a state inside a derived expression: https://svelte.dev/docs/svelte/runtime-errors#Client-errors-state_unsafe_mutation
|
||||||
|
*
|
||||||
|
* So, we need to use `toSorted` instead.
|
||||||
*/
|
*/
|
||||||
export let textWidth: ContainerWidth = 'normal';
|
let sortedLayouts = $derived(
|
||||||
|
layouts?.toSorted((a, b) => (a.breakpoint < b.breakpoint ? 1 : -1))
|
||||||
import Block from '../Block/Block.svelte';
|
|
||||||
import PaddingReset from '../PaddingReset/PaddingReset.svelte';
|
|
||||||
import Markdown from '../Markdown/Markdown.svelte';
|
|
||||||
|
|
||||||
let containerWidth: number;
|
|
||||||
|
|
||||||
const groupRows = (images: Image[], layout?: Layout) => {
|
|
||||||
// Default layout, one img per row
|
|
||||||
if (!layout) return images.map((img) => [img]);
|
|
||||||
// Otherwise, chunk into rows according to layout scheme
|
|
||||||
let i = 0;
|
|
||||||
const rows = [];
|
|
||||||
for (const rowLength of layout.rows) {
|
|
||||||
const row = [];
|
|
||||||
for (const imgI of [...Array(rowLength).keys()]) {
|
|
||||||
row.push(images[imgI + i]);
|
|
||||||
}
|
|
||||||
rows.push(row);
|
|
||||||
i += rowLength;
|
|
||||||
}
|
|
||||||
return rows;
|
|
||||||
};
|
|
||||||
// Sort so breakpoints always descend
|
|
||||||
$: layouts.sort((a, b) => (a.breakpoint < b.breakpoint ? 1 : -1));
|
|
||||||
$: layout = layouts.find(
|
|
||||||
(l) =>
|
|
||||||
// Must have valid rows schema, i.e., adds to the total number of images
|
|
||||||
l.rows.reduce((a, b) => a + b, 0) === images.length &&
|
|
||||||
// Breakpoint is higher than container width
|
|
||||||
(containerWidth || 0) >= l.breakpoint
|
|
||||||
);
|
);
|
||||||
$: rows = groupRows(images, layout);
|
|
||||||
|
let layout = $derived(
|
||||||
|
sortedLayouts?.find(
|
||||||
|
(l) =>
|
||||||
|
// Must have valid rows schema, i.e., adds to the total number of images
|
||||||
|
l.rows.reduce((a, b) => a + b, 0) === images.length &&
|
||||||
|
// Breakpoint is higher than container width
|
||||||
|
(containerWidth || 0) >= l.breakpoint
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
let rows = $derived(groupRows(images, layout));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Block {width} {id} class="photopack fmy-6 {cls}">
|
<Block {width} {id} class="photopack fmy-6 {cls}">
|
||||||
<div class="photopack-container w-full" bind:clientWidth="{containerWidth}">
|
<div class="photopack-container w-full" bind:clientWidth={containerWidth}>
|
||||||
{#each rows as row, ri}
|
{#each rows as row, ri}
|
||||||
<div
|
<div
|
||||||
class="photopack-row flex justify-between"
|
class="photopack-row flex justify-between"
|
||||||
style:gap="0 {gap}px"
|
style:gap="0 {gap}px"
|
||||||
style:margin-bottom="{ri < rows.length - 1 ? gap + 'px' : ''}"
|
style:margin-bottom={ri < rows.length - 1 ? gap + 'px' : ''}
|
||||||
>
|
>
|
||||||
{#each row as img, i}
|
{#each row as img, i}
|
||||||
<figure
|
<figure
|
||||||
|
|
@ -105,9 +95,9 @@
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="m-0 w-full h-full object-cover"
|
class="m-0 w-full h-full object-cover"
|
||||||
src="{img.src}"
|
src={img.src}
|
||||||
alt="{img.altText}"
|
alt={img.altText}
|
||||||
style:max-height="{img.maxHeight ? img.maxHeight + 'px' : ''}"
|
style:max-height={img.maxHeight ? img.maxHeight + 'px' : ''}
|
||||||
/>
|
/>
|
||||||
{#if !img.altText}
|
{#if !img.altText}
|
||||||
<div class="alt-warning absolute text-xxs py-1 px-2">altText</div>
|
<div class="alt-warning absolute text-xxs py-1 px-2">altText</div>
|
||||||
|
|
@ -117,14 +107,14 @@
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<PaddingReset containerIsFluid="{width === 'fluid'}">
|
<PaddingReset containerIsFluid={width === 'fluid'}>
|
||||||
<div class="notes contents">
|
<div class="notes contents">
|
||||||
<Block width="{textWidth}" class="photopack-captions-container">
|
<Block width={textWidth} class="photopack-captions-container">
|
||||||
{#each rows as row, ri}
|
{#each rows as row, ri}
|
||||||
{#each row as img, i}
|
{#each row as img, i}
|
||||||
{#if img.caption}
|
{#if img.caption}
|
||||||
<div id="{id}-figure-{ri}-{i}" class="caption">
|
<div id="{id}-figure-{ri}-{i}" class="caption">
|
||||||
<Markdown source="{img.caption}" />
|
<Markdown source={img.caption} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
```yaml
|
|
||||||
[blocks]
|
|
||||||
# ...
|
|
||||||
|
|
||||||
type: photo-pack
|
|
||||||
id: my-photo-pack
|
|
||||||
class: mb-2
|
|
||||||
width: wide
|
|
||||||
textWidth: normal
|
|
||||||
gap: 10
|
|
||||||
[.images]
|
|
||||||
src: images/my-img-1.jpg
|
|
||||||
altText: Alt text
|
|
||||||
caption: Lorem ipsum. REUTERS/Photog
|
|
||||||
|
|
||||||
src: images/my-img-2.jpg
|
|
||||||
altText: Alt text
|
|
||||||
caption: Lorem ipsum. REUTERS/Photog
|
|
||||||
|
|
||||||
src: images/my-img-3.jpg
|
|
||||||
altText: Alt text
|
|
||||||
caption: Lorem ipsum. REUTERS/Photog
|
|
||||||
|
|
||||||
src: images/my-img-4.jpg
|
|
||||||
altText: Alt text
|
|
||||||
caption: Lorem ipsum. REUTERS/Photog
|
|
||||||
|
|
||||||
src: images/my-img-5.jpg
|
|
||||||
altText: Alt text
|
|
||||||
caption: Lorem ipsum. REUTERS/Photog
|
|
||||||
[]
|
|
||||||
|
|
||||||
# ...
|
|
||||||
[]
|
|
||||||
```
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<!-- App.svelte -->
|
|
||||||
{#each content.blocks as block}
|
|
||||||
{#if block.type === 'text'}
|
|
||||||
<!-- ... -->
|
|
||||||
|
|
||||||
{:else if block.type === 'photo-pack'}
|
|
||||||
<PhotoPack
|
|
||||||
id={block.id}
|
|
||||||
class={block.class}
|
|
||||||
width={block.width}
|
|
||||||
textWidth={block.textWidth}
|
|
||||||
images={block.images.map((img) => ({
|
|
||||||
src: `${assets}/${img.src}`,
|
|
||||||
altText: img.altText,
|
|
||||||
caption: img.caption,
|
|
||||||
}))}
|
|
||||||
layouts={[
|
|
||||||
{ breakpoint: 750, rows: [2, 3] },
|
|
||||||
{ breakpoint: 450, rows: [1, 2, 2] },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- ... -->
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
```
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
The `PhotoPack` component makes simple photo grids with custom layouts at whatever breakpoint you need.
|
|
||||||
|
|
||||||
```svelte
|
|
||||||
<script>
|
|
||||||
import { PhotoPack } from '@reuters-graphics/graphics-components';
|
|
||||||
|
|
||||||
const images = [
|
|
||||||
{
|
|
||||||
src: 'https://...',
|
|
||||||
altText: 'Alt text',
|
|
||||||
caption: 'Lorem ipsum. REUTERS/Photog',
|
|
||||||
// Optional max-height of image across all layouts
|
|
||||||
maxHeight: 800,
|
|
||||||
},
|
|
||||||
// ...
|
|
||||||
];
|
|
||||||
|
|
||||||
const layouts = [
|
|
||||||
{
|
|
||||||
// Breakpoint above which this layout applies
|
|
||||||
breakpoint: 450,
|
|
||||||
// Number of photos in each row of this layout, adding up to the total number of images
|
|
||||||
rows: [1, 2, 1],
|
|
||||||
},
|
|
||||||
{ breakpoint: 750, rows: [1, 3] },
|
|
||||||
];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<PhotoPack images="{images}" layouts="{layouts}" />
|
|
||||||
```
|
|
||||||
|
|
||||||
`images` are defined with their src, alt text, captions and an optional `maxHeight`, which makes sure the image is no taller than that height in pixels in any layout.
|
|
||||||
|
|
||||||
`layouts` describe how those images will be laid out in rows at different breakpoints. The default layout (mobile-first) is each photo on its own row, stacked vertically, but you can group photos into `rows` above a `breakpoint` by specifying the number of photos that should go in that row. For example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const layouts = [{
|
|
||||||
breakpoint: 450,
|
|
||||||
rows: [1,2,1],
|
|
||||||
}];
|
|
||||||
```
|
|
||||||
|
|
||||||
... tells the component that when the `PhotoPack` container is 450 pixels or wider, it should group the 4 photos in 3 rows, 1 in the first, 2 in the second and 1 in the last.
|
|
||||||
|
|
||||||
You can define as many layouts for as many images as you like.
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
If any of your images is missing `altText` a small warning will overlay the photo.
|
|
||||||
18
src/components/PhotoPack/utils.ts
Normal file
18
src/components/PhotoPack/utils.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import type { Image, Layout } from './PhotoPack.svelte';
|
||||||
|
|
||||||
|
export const groupRows = (images: Image[], layout?: Layout) => {
|
||||||
|
// Default layout, one img per row
|
||||||
|
if (!layout) return images.map((img) => [img]);
|
||||||
|
// Otherwise, chunk into rows according to layout scheme
|
||||||
|
let i = 0;
|
||||||
|
const rows = [];
|
||||||
|
for (const rowLength of layout.rows) {
|
||||||
|
const row = [];
|
||||||
|
for (const imgI of [...Array(rowLength).keys()]) {
|
||||||
|
row.push(images[imgI + i]);
|
||||||
|
}
|
||||||
|
rows.push(row);
|
||||||
|
i += rowLength;
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
};
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<PymChild {...args} />
|
<PymChild {...args} />
|
||||||
<div>Nothing to see here. 😎</div>
|
<div>Nothing to see here. 😎</div>
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<ReferralBlock {...args} />
|
<ReferralBlock {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -49,21 +49,21 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
section: '/lifestyle/sports/',
|
section: '/lifestyle/sports/',
|
||||||
number: 4,
|
number: 4,
|
||||||
class: 'fmy-0',
|
class: 'fmy-0',
|
||||||
heading: 'More World Cup coverage',
|
heading: 'More World Cup coverage',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="By collection"
|
name="By collection"
|
||||||
args="{{
|
args={{
|
||||||
collection: 'x-trump',
|
collection: 'x-trump',
|
||||||
number: 6,
|
number: 6,
|
||||||
class: 'fmy-8',
|
class: 'fmy-8',
|
||||||
heading: 'The latest Trump coverage',
|
heading: 'The latest Trump coverage',
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(collectionDocs)}
|
{...withStoryDocs(collectionDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -96,33 +96,33 @@
|
||||||
<Block {width} {id} class="referrals-block {cls}">
|
<Block {width} {id} class="referrals-block {cls}">
|
||||||
<div
|
<div
|
||||||
class="block-container"
|
class="block-container"
|
||||||
class:stacked="{clientWidth && clientWidth < 750}"
|
class:stacked={clientWidth && clientWidth < 750}
|
||||||
bind:clientWidth
|
bind:clientWidth
|
||||||
>
|
>
|
||||||
{#if heading}
|
{#if heading}
|
||||||
<div
|
<div
|
||||||
class="heading h4 font-bold"
|
class="heading h4 font-bold"
|
||||||
class:stacked="{clientWidth && clientWidth < 750}"
|
class:stacked={clientWidth && clientWidth < 750}
|
||||||
>
|
>
|
||||||
{heading}
|
{heading}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div
|
<div
|
||||||
class="referral-container inline-flex flex-wrap w-full justify-between"
|
class="referral-container inline-flex flex-wrap w-full justify-between"
|
||||||
class:stacked="{clientWidth && clientWidth < 750}"
|
class:stacked={clientWidth && clientWidth < 750}
|
||||||
class:xs="{clientWidth && clientWidth < 450}"
|
class:xs={clientWidth && clientWidth < 450}
|
||||||
>
|
>
|
||||||
{#each referrals as referral}
|
{#each referrals as referral}
|
||||||
<div class="referral">
|
<div class="referral">
|
||||||
<a
|
<a
|
||||||
href="https://www.reuters.com{referral.canonical_url}"
|
href="https://www.reuters.com{referral.canonical_url}"
|
||||||
target="{linkTarget}"
|
target={linkTarget}
|
||||||
rel="{linkTarget === '_blank' ? 'noreferrer' : null}"
|
rel={linkTarget === '_blank' ? 'noreferrer' : null}
|
||||||
>
|
>
|
||||||
<div class="referral-pack flex justify-around my-0 mx-auto">
|
<div class="referral-pack flex justify-around my-0 mx-auto">
|
||||||
<div
|
<div
|
||||||
class="headline"
|
class="headline"
|
||||||
class:xs="{clientWidth && clientWidth < 450}"
|
class:xs={clientWidth && clientWidth < 450}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="kicker m-0 body-caption leading-tighter"
|
class="kicker m-0 body-caption leading-tighter"
|
||||||
|
|
@ -145,14 +145,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="image-container block m-0 overflow-hidden relative"
|
class="image-container block m-0 overflow-hidden relative"
|
||||||
class:xs="{clientWidth && clientWidth < 450}"
|
class:xs={clientWidth && clientWidth < 450}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
class="block object-cover m-0 w-full"
|
class="block object-cover m-0 w-full"
|
||||||
data-chromatic="ignore"
|
data-chromatic="ignore"
|
||||||
src="{referral.thumbnail.renditions.landscape['240w']}"
|
src={referral.thumbnail.renditions.landscape['240w']}
|
||||||
alt="{referral.thumbnail.caption ||
|
alt={referral.thumbnail.caption ||
|
||||||
referral.thumbnail.alt_text}"
|
referral.thumbnail.alt_text}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
{#if preload === 0 || (i >= (stackBackground ? 0 : index - preload) && i <= index + preload)}
|
{#if preload === 0 || (i >= (stackBackground ? 0 : index - preload) && i <= index + preload)}
|
||||||
<div
|
<div
|
||||||
class="step-background step-{i + 1} w-full absolute"
|
class="step-background step-{i + 1} w-full absolute"
|
||||||
class:visible="{stackBackground ? i <= index : i === index}"
|
class:visible={stackBackground ? i <= index : i === index}
|
||||||
class:invisible="{stackBackground ? i > index : i !== index}"
|
class:invisible={stackBackground ? i > index : i !== index}
|
||||||
>
|
>
|
||||||
<step.background {...step.backgroundProps || {}}></step.background>
|
<step.background {...step.backgroundProps || {}}></step.background>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
let { step, backgroundWidth, index }: Props = $props();
|
let { step, backgroundWidth, index }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Block width="{backgroundWidth}" class="background-container step-{index + 1}">
|
<Block width={backgroundWidth} class="background-container step-{index + 1}">
|
||||||
<div class="embedded-background step-{index + 1}" aria-hidden="true">
|
<div class="embedded-background step-{index + 1}" aria-hidden="true">
|
||||||
<step.background {...step.backgroundProps || {}}></step.background>
|
<step.background {...step.backgroundProps || {}}></step.background>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -17,18 +17,18 @@
|
||||||
|
|
||||||
{#if typeof step.altText === 'string'}
|
{#if typeof step.altText === 'string'}
|
||||||
<div class="background-alt-text visually-hidden">
|
<div class="background-alt-text visually-hidden">
|
||||||
<Markdown source="{step.altText}" />
|
<Markdown source={step.altText} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if typeof step.foreground === 'string'}
|
{:else if typeof step.foreground === 'string'}
|
||||||
<Block class="body-text step-{index + 1}">
|
<Block class="body-text step-{index + 1}">
|
||||||
<div class="embedded-foreground step-{index + 1}">
|
<div class="embedded-foreground step-{index + 1}">
|
||||||
<Markdown source="{step.foreground}" />
|
<Markdown source={step.foreground} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if typeof step.altText === 'string'}
|
{#if typeof step.altText === 'string'}
|
||||||
<div class="background-alt-text visually-hidden">
|
<div class="background-alt-text visually-hidden">
|
||||||
<Markdown source="{step.altText}" />
|
<Markdown source={step.altText} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -19,20 +19,20 @@
|
||||||
<div class="empty-step-foreground"></div>
|
<div class="empty-step-foreground"></div>
|
||||||
{#if typeof step.altText === 'string'}
|
{#if typeof step.altText === 'string'}
|
||||||
<div class="background-alt-text visually-hidden">
|
<div class="background-alt-text visually-hidden">
|
||||||
<Markdown source="{step.altText}" />
|
<Markdown source={step.altText} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="step-foreground w-full">
|
<div class="step-foreground w-full">
|
||||||
{#if typeof step.foreground === 'string'}
|
{#if typeof step.foreground === 'string'}
|
||||||
<Markdown source="{step.foreground}" />
|
<Markdown source={step.foreground} />
|
||||||
{:else}
|
{:else}
|
||||||
<step.foreground {...step.foregroundProps || {}}></step.foreground>
|
<step.foreground {...step.foregroundProps || {}}></step.foreground>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if typeof step.altText === 'string'}
|
{#if typeof step.altText === 'string'}
|
||||||
<div class="background-alt-text visually-hidden">
|
<div class="background-alt-text visually-hidden">
|
||||||
<Markdown source="{step.altText}" />
|
<Markdown source={step.altText} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Scroller {...args} />
|
<Scroller {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
background: BasicStep,
|
background: BasicStep,
|
||||||
|
|
@ -112,14 +112,14 @@
|
||||||
backgroundWidth: 'fluid',
|
backgroundWidth: 'fluid',
|
||||||
embeddedLayout: 'fb',
|
embeddedLayout: 'fb',
|
||||||
embedded: false,
|
embedded: false,
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="ArchieML" args="{docBlock}" {...withStoryDocs(archieMLDocs)} />
|
<Story name="ArchieML" args={docBlock} {...withStoryDocs(archieMLDocs)} />
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Foreground components"
|
name="Foreground components"
|
||||||
args="{{
|
args={{
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
background: BasicStep,
|
background: BasicStep,
|
||||||
|
|
@ -142,13 +142,13 @@
|
||||||
backgroundWidth: 'fluid',
|
backgroundWidth: 'fluid',
|
||||||
embeddedLayout: 'fb',
|
embeddedLayout: 'fb',
|
||||||
embedded: false,
|
embedded: false,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(interactiveDocs)}
|
{...withStoryDocs(interactiveDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Ai2svelte"
|
name="Ai2svelte"
|
||||||
args="{{
|
args={{
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
background: AiMap1,
|
background: AiMap1,
|
||||||
|
|
@ -175,6 +175,6 @@
|
||||||
backgroundWidth: 'fluid',
|
backgroundWidth: 'fluid',
|
||||||
embeddedLayout: 'fb',
|
embeddedLayout: 'fb',
|
||||||
embedded: false,
|
embedded: false,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(ai2svelteDocs)}
|
{...withStoryDocs(ai2svelteDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -123,13 +123,13 @@
|
||||||
<div
|
<div
|
||||||
slot="background"
|
slot="background"
|
||||||
class="background min-h-screen relative p-0 flex justify-center"
|
class="background min-h-screen relative p-0 flex justify-center"
|
||||||
class:right="{foregroundPosition === 'left opposite'}"
|
class:right={foregroundPosition === 'left opposite'}
|
||||||
class:left="{foregroundPosition === 'right opposite'}"
|
class:left={foregroundPosition === 'right opposite'}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<div class="scroller-graphic-well w-full">
|
<div class="scroller-graphic-well w-full">
|
||||||
<Block
|
<Block
|
||||||
width="{backgroundWidth}"
|
width={backgroundWidth}
|
||||||
class="background-container step-{index +
|
class="background-container step-{index +
|
||||||
1} my-0 min-h-screen flex justify-center items-center relative"
|
1} my-0 min-h-screen flex justify-center items-center relative"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:21 -->
|
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:21 -->
|
||||||
|
|
||||||
<div id="g-step-1-box" bind:clientWidth="{width}">
|
<div id="g-step-1-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: XL -->
|
<!-- Artboard: XL -->
|
||||||
{#if width && width >= 1200}
|
{#if width && width >= 1200}
|
||||||
<div id="g-step-1-xl" class="g-artboard" style="">
|
<div id="g-step-1-xl" class="g-artboard" style="">
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:20 -->
|
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:20 -->
|
||||||
|
|
||||||
<div id="g-step-2-box" bind:clientWidth="{width}">
|
<div id="g-step-2-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: XL -->
|
<!-- Artboard: XL -->
|
||||||
{#if width && width >= 1200}
|
{#if width && width >= 1200}
|
||||||
<div id="g-step-2-xl" class="g-artboard" style="">
|
<div id="g-step-2-xl" class="g-artboard" style="">
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:28 -->
|
<!-- Generated by ai2html v0.100.0 - 2021-09-30 14:28 -->
|
||||||
|
|
||||||
<div id="g-step-3-box" bind:clientWidth="{width}">
|
<div id="g-step-3-box" bind:clientWidth={width}>
|
||||||
<!-- Artboard: XL -->
|
<!-- Artboard: XL -->
|
||||||
{#if width && width >= 1200}
|
{#if width && width >= 1200}
|
||||||
<div id="g-step-3-xl" class="g-artboard" style="">
|
<div id="g-step-3-xl" class="g-artboard" style="">
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<p>The count is {count}</p>
|
<p>The count is {count}</p>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onclick="{() => {
|
onclick={() => {
|
||||||
count += 1;
|
count += 1;
|
||||||
}}">Click Me</button
|
}}>Click Me</button
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
let { colour = 'lightblue' }: Props = $props();
|
let { colour = 'lightblue' }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="step" style="{`background: ${colour};`}"></div>
|
<div class="step" style={`background: ${colour};`}></div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.step {
|
.step {
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<SearchInput {...args} />
|
<SearchInput {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Template>
|
</Template>
|
||||||
|
|
||||||
<Story name="Default" args="{{}}" />
|
<Story name="Default" args={{}} />
|
||||||
|
|
|
||||||
|
|
@ -38,17 +38,17 @@
|
||||||
id="search--input"
|
id="search--input"
|
||||||
class="search--input body-caption pl-8"
|
class="search--input body-caption pl-8"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="{searchPlaceholder}"
|
placeholder={searchPlaceholder}
|
||||||
oninput="{input}"
|
oninput={input}
|
||||||
bind:value
|
bind:value
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="search--x absolute"
|
class="search--x absolute"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class:invisible="{!active}"
|
class:invisible={!active}
|
||||||
onclick="{clear}"
|
onclick={clear}
|
||||||
onkeyup="{clear}"
|
onkeyup={clear}
|
||||||
>
|
>
|
||||||
<X />
|
<X />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
{#each links.social_links as link}
|
{#each links.social_links as link}
|
||||||
{@const SvelteComponent = symbols[link.type]}
|
{@const SvelteComponent = symbols[link.type]}
|
||||||
<li class="social-links symbol">
|
<li class="social-links symbol">
|
||||||
<a href="{normalizeUrl(link.url)}">
|
<a href={normalizeUrl(link.url)}>
|
||||||
<div class="button">
|
<div class="button">
|
||||||
<div class="social">
|
<div class="social">
|
||||||
<SvelteComponent />
|
<SvelteComponent />
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
<ul class="link-group">
|
<ul class="link-group">
|
||||||
{#each links.ad_links as link}
|
{#each links.ad_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">
|
<a href={normalizeUrl(link.url)}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
</section>
|
</section>
|
||||||
<p class="disclaimer">
|
<p class="disclaimer">
|
||||||
All quotes delayed a minimum of 15 minutes. <a
|
All quotes delayed a minimum of 15 minutes. <a
|
||||||
href="{normalizeUrl(links.disclaimer_link)}"
|
href={normalizeUrl(links.disclaimer_link)}
|
||||||
>See here for a complete list of exchanges and delays</a
|
>See here for a complete list of exchanges and delays</a
|
||||||
>.
|
>.
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
<ul class="link-group">
|
<ul class="link-group">
|
||||||
{#each links.misc_links.filter((d) => !d.self) as link}
|
{#each links.misc_links.filter((d) => !d.self) as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">
|
<a href={normalizeUrl(link.url)}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
</section>
|
</section>
|
||||||
<p class="copyright">
|
<p class="copyright">
|
||||||
© {links.copyright_year} Reuters.
|
© {links.copyright_year} Reuters.
|
||||||
<a href="{normalizeUrl(links.copyright_link)}">All rights reserved</a>
|
<a href={normalizeUrl(links.copyright_link)}>All rights reserved</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
const mobileBreakpoint = 745;
|
const mobileBreakpoint = 745;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerWidth="{windowWidth}" />
|
<svelte:window bind:innerWidth={windowWidth} />
|
||||||
|
|
||||||
{#if links.latest_links}
|
{#if links.latest_links}
|
||||||
<section class="quick-links">
|
<section class="quick-links">
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each links.latest_links as link}
|
{#each links.latest_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">{link.text}</a>
|
<a href={normalizeUrl(link.url)}>{link.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -44,7 +44,7 @@
|
||||||
<div class="symbol">
|
<div class="symbol">
|
||||||
<SvelteComponent />
|
<SvelteComponent />
|
||||||
</div>
|
</div>
|
||||||
<a href="{normalizeUrl(link.url)}">
|
<a href={normalizeUrl(link.url)}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each links.latest_links as link}
|
{#each links.latest_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">{link.text}</a>
|
<a href={normalizeUrl(link.url)}>{link.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each links.browse_links as link}
|
{#each links.browse_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">{link.text}</a>
|
<a href={normalizeUrl(link.url)}>{link.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -85,7 +85,7 @@
|
||||||
<div class="symbol">
|
<div class="symbol">
|
||||||
<SvelteComponent_1 />
|
<SvelteComponent_1 />
|
||||||
</div>
|
</div>
|
||||||
<a href="{normalizeUrl(link.url)}">
|
<a href={normalizeUrl(link.url)}>
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each links.about_links as link}
|
{#each links.about_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">{link.text}</a>
|
<a href={normalizeUrl(link.url)}>{link.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -109,7 +109,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each links.stay_informed_links as link}
|
{#each links.stay_informed_links as link}
|
||||||
<li>
|
<li>
|
||||||
<a href="{normalizeUrl(link.url)}">{link.text}</a>
|
<a href={normalizeUrl(link.url)}>{link.text}</a>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
import Theme from '../Theme/Theme.svelte';
|
import Theme from '../Theme/Theme.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<div>
|
<div>
|
||||||
<SiteFooter {...args} />
|
<SiteFooter {...args} />
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Remove referrals"
|
name="Remove referrals"
|
||||||
args="{{ includeReferrals: false }}"
|
args={{ includeReferrals: false }}
|
||||||
{...withStoryDocs(removeReferralsDocs)}
|
{...withStoryDocs(removeReferralsDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,12 +44,12 @@
|
||||||
|
|
||||||
<footer
|
<footer
|
||||||
class="my-0"
|
class="my-0"
|
||||||
style="{`
|
style={`
|
||||||
--nav-background: var(--theme-colour-background, #fff);
|
--nav-background: var(--theme-colour-background, #fff);
|
||||||
--nav-primary: var(--theme-colour-text-primary, #404040);
|
--nav-primary: var(--theme-colour-text-primary, #404040);
|
||||||
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
||||||
--theme-font-family-sans-serif: Knowledge, sans-serif;
|
--theme-font-family-sans-serif: Knowledge, sans-serif;
|
||||||
`}"
|
`}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{#if includeReferrals}
|
{#if includeReferrals}
|
||||||
|
|
@ -61,9 +61,9 @@
|
||||||
/>
|
/>
|
||||||
</PaddingReset>
|
</PaddingReset>
|
||||||
{/if}
|
{/if}
|
||||||
<QuickLinks links="{data[0]}" />
|
<QuickLinks links={data[0]} />
|
||||||
<CompanyLinks links="{data[0]}" />
|
<CompanyLinks links={data[0]} />
|
||||||
<LegalLinks links="{data[0]}" />
|
<LegalLinks links={data[0]} />
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,13 @@
|
||||||
<div
|
<div
|
||||||
class="overlay"
|
class="overlay"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
style="{`
|
style={`
|
||||||
--nav-background: var(--theme-colour-background, #fff);
|
--nav-background: var(--theme-colour-background, #fff);
|
||||||
--nav-primary: var(--theme-colour-text-primary, #404040);
|
--nav-primary: var(--theme-colour-text-primary, #404040);
|
||||||
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
||||||
--nav-accent: var(--theme-colour-brand-logo, #fa6400);
|
--nav-accent: var(--theme-colour-brand-logo, #fa6400);
|
||||||
--nav-shadow: 0 1px 4px 2px var(--theme-colour-brand-shadow, rgba(64,64,64,.08));
|
--nav-shadow: 0 1px 4px 2px var(--theme-colour-brand-shadow, rgba(64,64,64,.08));
|
||||||
`}"
|
`}
|
||||||
>
|
>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
textColour="var(--nav-primary)"
|
textColour="var(--nav-primary)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button class="button close-button" onclick="{releaseMobileMenu}">
|
<button class="button close-button" onclick={releaseMobileMenu}>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -43,14 +43,14 @@
|
||||||
</header>
|
</header>
|
||||||
{#each data.sections as section}
|
{#each data.sections as section}
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<a class="section-link" href="{normalizeUrl(section.url)}"
|
<a class="section-link" href={normalizeUrl(section.url)}
|
||||||
>{section.name}</a
|
>{section.name}</a
|
||||||
>
|
>
|
||||||
{#if section.children}
|
{#if section.children}
|
||||||
<ul class="subsections">
|
<ul class="subsections">
|
||||||
{#each section.children as sub}
|
{#each section.children as sub}
|
||||||
<li>
|
<li>
|
||||||
<a class="subsection-link" href="{normalizeUrl(sub.url)}">
|
<a class="subsection-link" href={normalizeUrl(sub.url)}>
|
||||||
{sub.name}
|
{sub.name}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
class="arrow"
|
class="arrow"
|
||||||
class:rotated="{rotate}"
|
class:rotated={rotate}
|
||||||
focusable="false"
|
focusable="false"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,16 @@
|
||||||
{#each sections as section}
|
{#each sections as section}
|
||||||
<section
|
<section
|
||||||
class="more-section-group"
|
class="more-section-group"
|
||||||
class:has-children="{section.children}"
|
class:has-children={section.children}
|
||||||
>
|
>
|
||||||
<a href="{normalizeUrl(section.url)}" class="section-link">
|
<a href={normalizeUrl(section.url)} class="section-link">
|
||||||
{section.name}
|
{section.name}
|
||||||
</a>
|
</a>
|
||||||
{#if section.children}
|
{#if section.children}
|
||||||
<ul class="subsections">
|
<ul class="subsections">
|
||||||
{#each section.children as sub}
|
{#each section.children as sub}
|
||||||
<li>
|
<li>
|
||||||
<a class="subsection-link" href="{normalizeUrl(sub.url)}"
|
<a class="subsection-link" href={normalizeUrl(sub.url)}
|
||||||
>{sub.name}</a
|
>{sub.name}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<NavDropdown {headingText}>
|
<NavDropdown {headingText}>
|
||||||
<a href="{normalizeUrl(section.url)}">
|
<a href={normalizeUrl(section.url)}>
|
||||||
<span class="heading">
|
<span class="heading">
|
||||||
Browse {section.name}
|
Browse {section.name}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<ul class="sections-group">
|
<ul class="sections-group">
|
||||||
{#each section.children.slice(0, splitCount) as sub}
|
{#each section.children.slice(0, splitCount) as sub}
|
||||||
<li>
|
<li>
|
||||||
<a class="subsection-link" href="{normalizeUrl(sub.url)}">
|
<a class="subsection-link" href={normalizeUrl(sub.url)}>
|
||||||
{sub.name}
|
{sub.name}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<ul class="sections-group">
|
<ul class="sections-group">
|
||||||
{#each section.children.slice(splitCount) as sub}
|
{#each section.children.slice(splitCount) as sub}
|
||||||
<li>
|
<li>
|
||||||
<a class="subsection-link" href="{normalizeUrl(sub.url)}">
|
<a class="subsection-link" href={normalizeUrl(sub.url)}>
|
||||||
{sub.name}
|
{sub.name}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,16 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="story-card">
|
<div class="story-card">
|
||||||
<a href="{normalizeUrl(story.canonical_url)}">
|
<a href={normalizeUrl(story.canonical_url)}>
|
||||||
<div class="story-text" class:has-thumbnail="{thumbnail}">
|
<div class="story-text" class:has-thumbnail={thumbnail}>
|
||||||
<span>{story.title}</span>
|
<span>{story.title}</span>
|
||||||
<time datetime="{story.display_time}">{getTime(story.display_time)}</time>
|
<time datetime={story.display_time}>{getTime(story.display_time)}</time>
|
||||||
</div>
|
</div>
|
||||||
{#if thumbnail}
|
{#if thumbnail}
|
||||||
<div class="thumbnail">
|
<div class="thumbnail">
|
||||||
<img
|
<img
|
||||||
src="{thumbnail.renditions.square['120w']}"
|
src={thumbnail.renditions.square['120w']}
|
||||||
alt="{thumbnail.alt_text}"
|
alt={thumbnail.alt_text}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
let hiddenSections = $derived(sections.slice(displayCount));
|
let hiddenSections = $derived(sections.slice(displayCount));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerWidth="{windowWidth}" />
|
<svelte:window bind:innerWidth={windowWidth} />
|
||||||
|
|
||||||
<div class="nav-bar">
|
<div class="nav-bar">
|
||||||
<nav aria-label="Main navigation">
|
<nav aria-label="Main navigation">
|
||||||
|
|
@ -35,50 +35,50 @@
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<li
|
<li
|
||||||
class="nav-item category link"
|
class="nav-item category link"
|
||||||
onmouseenter="{() => {
|
onmouseenter={() => {
|
||||||
navTimeout = setTimeout(
|
navTimeout = setTimeout(
|
||||||
() => activeSection.set(section.id),
|
() => activeSection.set(section.id),
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
}}"
|
}}
|
||||||
onfocus="{() => activeSection.set(section.id)}"
|
onfocus={() => activeSection.set(section.id)}
|
||||||
onmouseleave="{() => {
|
onmouseleave={() => {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}}"
|
}}
|
||||||
onblur="{() => {
|
onblur={() => {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}}"
|
}}
|
||||||
onclick="{() => {
|
onclick={() => {
|
||||||
if ($activeSection === section.id) {
|
if ($activeSection === section.id) {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="nav-button link"
|
class="nav-button link"
|
||||||
class:open="{section.id === $activeSection}"
|
class:open={section.id === $activeSection}
|
||||||
>
|
>
|
||||||
<a href="{normalizeUrl(section.url)}">
|
<a href={normalizeUrl(section.url)}>
|
||||||
{section.name}
|
{section.name}
|
||||||
</a>
|
</a>
|
||||||
<button class="button">
|
<button class="button">
|
||||||
<DownArrow rotate="{section.id === $activeSection}" />
|
<DownArrow rotate={section.id === $activeSection} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if $activeSection === section.id}
|
{#if $activeSection === section.id}
|
||||||
<SectionDropdown
|
<SectionDropdown
|
||||||
{section}
|
{section}
|
||||||
headingText="{`Latest in ${section.name}`}"
|
headingText={`Latest in ${section.name}`}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{:else}
|
{:else}
|
||||||
<li class="nav-item category link">
|
<li class="nav-item category link">
|
||||||
<div class="nav-button link">
|
<div class="nav-button link">
|
||||||
<a href="{normalizeUrl(section.url)}">
|
<a href={normalizeUrl(section.url)}>
|
||||||
{section.name}
|
{section.name}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -88,35 +88,35 @@
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<li
|
<li
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
onmouseenter="{() => {
|
onmouseenter={() => {
|
||||||
navTimeout = setTimeout(() => activeSection.set('more'), timeout);
|
navTimeout = setTimeout(() => activeSection.set('more'), timeout);
|
||||||
}}"
|
}}
|
||||||
onfocus="{() => activeSection.set('more')}"
|
onfocus={() => activeSection.set('more')}
|
||||||
onmouseleave="{() => {
|
onmouseleave={() => {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}}"
|
}}
|
||||||
onblur="{() => {
|
onblur={() => {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}}"
|
}}
|
||||||
onclick="{() => {
|
onclick={() => {
|
||||||
if ($activeSection === 'more') {
|
if ($activeSection === 'more') {
|
||||||
clearTimeout(navTimeout);
|
clearTimeout(navTimeout);
|
||||||
activeSection.set(null);
|
activeSection.set(null);
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="nav-button more link"
|
class="nav-button more link"
|
||||||
class:open="{$activeSection === 'more'}"
|
class:open={$activeSection === 'more'}
|
||||||
>
|
>
|
||||||
<button class="button">
|
<button class="button">
|
||||||
<span>More <DownArrow rotate="{$activeSection === 'more'}" /></span>
|
<span>More <DownArrow rotate={$activeSection === 'more'} /></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if $activeSection === 'more'}
|
{#if $activeSection === 'more'}
|
||||||
<MoreDropdown sections="{hiddenSections}" />
|
<MoreDropdown sections={hiddenSections} />
|
||||||
{/if}
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
import Theme from '../Theme/Theme.svelte';
|
import Theme from '../Theme/Theme.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<div>
|
<div>
|
||||||
<SiteHeader {...args} />
|
<SiteHeader {...args} />
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,14 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header
|
<header
|
||||||
style="{`
|
style={`
|
||||||
--nav-background: var(--theme-colour-background, #fff);
|
--nav-background: var(--theme-colour-background, #fff);
|
||||||
--nav-primary: var(--theme-colour-text-primary, #404040);
|
--nav-primary: var(--theme-colour-text-primary, #404040);
|
||||||
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
--nav-rules: var(--theme-colour-brand-rules, #d0d0d0);
|
||||||
--nav-accent: var(--theme-colour-brand-logo, #fa6400);
|
--nav-accent: var(--theme-colour-brand-logo, #fa6400);
|
||||||
--nav-shadow: 0 1px 4px 2px var(--theme-colour-brand-shadow, rgb(255 255 255 / 10%));
|
--nav-shadow: 0 1px 4px 2px var(--theme-colour-brand-shadow, rgb(255 255 255 / 10%));
|
||||||
--theme-font-family-sans-serif: Knowledge, sans-serif;
|
--theme-font-family-sans-serif: Knowledge, sans-serif;
|
||||||
`}"
|
`}
|
||||||
>
|
>
|
||||||
<a href="#main-content" class="skip-link"> Skip to main content </a>
|
<a href="#main-content" class="skip-link"> Skip to main content </a>
|
||||||
<div class="nav-container show-nav">
|
<div class="nav-container show-nav">
|
||||||
|
|
@ -76,10 +76,10 @@
|
||||||
class="menu-button"
|
class="menu-button"
|
||||||
aria-label="Menu"
|
aria-label="Menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="{isMobileMenuOpen}"
|
aria-expanded={isMobileMenuOpen}
|
||||||
onclick="{() => {
|
onclick={() => {
|
||||||
isMobileMenuOpen = !isMobileMenuOpen;
|
isMobileMenuOpen = !isMobileMenuOpen;
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
|
|
@ -95,10 +95,10 @@
|
||||||
|
|
||||||
<MobileMenu
|
<MobileMenu
|
||||||
{isMobileMenuOpen}
|
{isMobileMenuOpen}
|
||||||
releaseMobileMenu="{() => {
|
releaseMobileMenu={() => {
|
||||||
isMobileMenuOpen = false;
|
isMobileMenuOpen = false;
|
||||||
}}"
|
}}
|
||||||
data="{data[0]}"
|
data={data[0]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<SiteHeadline {...args} />
|
<SiteHeadline {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
section: 'Graphics',
|
section: 'Graphics',
|
||||||
sectionUrl: 'https://graphics.reuters.com',
|
sectionUrl: 'https://graphics.reuters.com',
|
||||||
hed: 'Ukraine makes surprising gains in counteroffensive',
|
hed: 'Ukraine makes surprising gains in counteroffensive',
|
||||||
|
|
@ -55,15 +55,15 @@
|
||||||
],
|
],
|
||||||
publishTime: new Date('2021-09-12').toISOString(),
|
publishTime: new Date('2021-09-12').toISOString(),
|
||||||
updateTime: new Date('2021-09-12T13:57:00').toISOString(),
|
updateTime: new Date('2021-09-12T13:57:00').toISOString(),
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="ArchieML" {...withStoryDocs(archieML)}>
|
<Story name="ArchieML" {...withStoryDocs(archieML)}>
|
||||||
<SiteHeadline
|
<SiteHeadline
|
||||||
hed="{content.Hed}"
|
hed={content.Hed}
|
||||||
section="{content.Section}"
|
section={content.Section}
|
||||||
sectionUrl="{content.SectionUrl}"
|
sectionUrl={content.SectionUrl}
|
||||||
authors="{content.Authors.split(',')}"
|
authors={content.Authors.split(',')}
|
||||||
publishTime="{content.Published}"
|
publishTime={content.Published}
|
||||||
/>
|
/>
|
||||||
</Story>
|
</Story>
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@
|
||||||
class="section-title mb-0 font-subhed text-xs text-secondary font-bold uppercase whitespace-nowrap tracking-wider"
|
class="section-title mb-0 font-subhed text-xs text-secondary font-bold uppercase whitespace-nowrap tracking-wider"
|
||||||
>
|
>
|
||||||
{#if sectionUrl}
|
{#if sectionUrl}
|
||||||
<a class="no-underline !text-secondary" href="{sectionUrl}"
|
<a class="no-underline !text-secondary" href={sectionUrl}
|
||||||
>{section}</a
|
>{section}</a
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Spinner {...args} />
|
<Spinner {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style:width="100%"
|
style:width="100%"
|
||||||
style:height="{`${width + containerPadding * 2}px`}"
|
style:height={`${width + containerPadding * 2}px`}
|
||||||
class="component-container flex items-center justify-center"
|
class="component-container flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<nav aria-label="pagination" class="pagination fmt-4">
|
<nav aria-label="pagination" class="pagination fmt-4">
|
||||||
<button onclick="{goToPreviousPage}" disabled="{pageNumber === 1}"
|
<button onclick={goToPreviousPage} disabled={pageNumber === 1}
|
||||||
><div class="icon-wrapper">
|
><div class="icon-wrapper">
|
||||||
<LeftArrow />
|
<LeftArrow />
|
||||||
<span class="visually-hidden">Previous page</span>
|
<span class="visually-hidden">Previous page</span>
|
||||||
|
|
@ -63,8 +63,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onclick="{goToNextPage}"
|
onclick={goToNextPage}
|
||||||
disabled="{pageNumber === Math.ceil(n / pageSize)}"
|
disabled={pageNumber === Math.ceil(n / pageSize)}
|
||||||
><div class="icon-wrapper">
|
><div class="icon-wrapper">
|
||||||
<RightArrow />
|
<RightArrow />
|
||||||
<span class="visually-hidden">Next page</span>
|
<span class="visually-hidden">Next page</span>
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
class="select--input body-caption fpx-2"
|
class="select--input body-caption fpx-2"
|
||||||
name="select--input"
|
name="select--input"
|
||||||
id="select--input"
|
id="select--input"
|
||||||
oninput="{input}"
|
oninput={input}
|
||||||
>
|
>
|
||||||
{#each options as obj}
|
{#each options as obj}
|
||||||
<option value="{obj.value}">{obj.text}</option>
|
<option value={obj.value}>{obj.text}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@
|
||||||
class="avoid-clicks"
|
class="avoid-clicks"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
class:active="{sortDirection === 'descending' && active}"
|
class:active={sortDirection === 'descending' && active}
|
||||||
d="M6.76474 20.2244L0.236082 13.4649C-0.0786943 13.139 -0.0786943 12.6104 0.236082 12.2845C0.550521 11.959 1.19794 11.96 1.51305 12.2845L7.33483 12.2845L13 12.2845C13.43 11.8545 14.1195 11.9593 14.4339 12.2849C14.7487 12.6107 14.7487 13.1394 14.4339 13.4653L7.90492 20.2244C7.59015 20.5503 7.07952 20.5503 6.76474 20.2244Z"
|
d="M6.76474 20.2244L0.236082 13.4649C-0.0786943 13.139 -0.0786943 12.6104 0.236082 12.2845C0.550521 11.959 1.19794 11.96 1.51305 12.2845L7.33483 12.2845L13 12.2845C13.43 11.8545 14.1195 11.9593 14.4339 12.2849C14.7487 12.6107 14.7487 13.1394 14.4339 13.4653L7.90492 20.2244C7.59015 20.5503 7.07952 20.5503 6.76474 20.2244Z"
|
||||||
></path>
|
></path>
|
||||||
<path
|
<path
|
||||||
class:active="{sortDirection === 'ascending' && active}"
|
class:active={sortDirection === 'ascending' && active}
|
||||||
d="M7.90518 0.244414L14.4338 7.00385C14.7486 7.32973 14.7486 7.85838 14.4338 8.18427C14.1194 8.50981 13.472 8.50876 13.1569 8.18427L7.33509 8.18427L1.66992 8.18427C1.23992 8.61427 0.550443 8.50946 0.236003 8.18392C-0.0787725 7.85803 -0.0787725 7.32938 0.236003 7.0035L6.765 0.244414C7.07978 -0.0814713 7.5904 -0.0814713 7.90518 0.244414Z"
|
d="M7.90518 0.244414L14.4338 7.00385C14.7486 7.32973 14.7486 7.85838 14.4338 8.18427C14.1194 8.50981 13.472 8.50876 13.1569 8.18427L7.33509 8.18427L1.66992 8.18427C1.23992 8.61427 0.550443 8.50946 0.236003 8.18392C-0.0787725 7.85803 -0.0787725 7.32938 0.236003 7.0035L6.765 0.244414C7.07978 -0.0814713 7.5904 -0.0814713 7.90518 0.244414Z"
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@
|
||||||
const currencyFormat = (v: number) => '$' + v.toFixed(1);
|
const currencyFormat = (v: number) => '$' + v.toFixed(1);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Table {...args} />
|
<Table {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -55,74 +55,74 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
data: homeRuns,
|
data: homeRuns,
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Metadata"
|
name="Metadata"
|
||||||
{...withStoryDocs(metadataDocs)}
|
{...withStoryDocs(metadataDocs)}
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
data: homeRuns,
|
data: homeRuns,
|
||||||
title: 'Career home run leaders',
|
title: 'Career home run leaders',
|
||||||
dek: 'In baseball, a home run (also known as a "dinger" or "tater") occurs when a batter hits the ball over the outfield fence. When a home run is hit, the batter and any runners on base are able to score.',
|
dek: 'In baseball, a home run (also known as a "dinger" or "tater") occurs when a batter hits the ball over the outfield fence. When a home run is hit, the batter and any runners on base are able to score.',
|
||||||
notes: 'Note: As of Opening Day 2023',
|
notes: 'Note: As of Opening Day 2023',
|
||||||
source: 'Source: Baseball Reference',
|
source: 'Source: Baseball Reference',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Truncate"
|
name="Truncate"
|
||||||
{...withStoryDocs(truncateDocs)}
|
{...withStoryDocs(truncateDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: homeRuns,
|
data: homeRuns,
|
||||||
truncated: true,
|
truncated: true,
|
||||||
source: 'Source: Baseball Reference',
|
source: 'Source: Baseball Reference',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Paginate"
|
name="Paginate"
|
||||||
{...withStoryDocs(paginateDocs)}
|
{...withStoryDocs(paginateDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: pressFreedom,
|
data: pressFreedom,
|
||||||
title: 'Press Freedom Index',
|
title: 'Press Freedom Index',
|
||||||
paginated: true,
|
paginated: true,
|
||||||
source: 'Source: Reporters Without Borders',
|
source: 'Source: Reporters Without Borders',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Search"
|
name="Search"
|
||||||
{...withStoryDocs(searchDocs)}
|
{...withStoryDocs(searchDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: pressFreedom,
|
data: pressFreedom,
|
||||||
searchable: true,
|
searchable: true,
|
||||||
paginated: true,
|
paginated: true,
|
||||||
title: 'Press Freedom Index',
|
title: 'Press Freedom Index',
|
||||||
source: 'Source: Reporters Without Borders',
|
source: 'Source: Reporters Without Borders',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Filter"
|
name="Filter"
|
||||||
{...withStoryDocs(filterDocs)}
|
{...withStoryDocs(filterDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: pressFreedom,
|
data: pressFreedom,
|
||||||
paginated: true,
|
paginated: true,
|
||||||
filterField: 'Region',
|
filterField: 'Region',
|
||||||
title: 'Press Freedom Index',
|
title: 'Press Freedom Index',
|
||||||
notes: 'Source: Reporters Without Borders',
|
notes: 'Source: Reporters Without Borders',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Search and filter"
|
name="Search and filter"
|
||||||
{...withStoryDocs(bothDocs)}
|
{...withStoryDocs(bothDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: pressFreedom,
|
data: pressFreedom,
|
||||||
searchable: true,
|
searchable: true,
|
||||||
filterField: 'Region',
|
filterField: 'Region',
|
||||||
|
|
@ -130,13 +130,13 @@
|
||||||
title: 'Press Freedom Index',
|
title: 'Press Freedom Index',
|
||||||
dek: 'Reporters Without Borders ranks countries based on their level of press freedom using criteria such as the degree of media pluralism and violence against journalists.',
|
dek: 'Reporters Without Borders ranks countries based on their level of press freedom using criteria such as the degree of media pluralism and violence against journalists.',
|
||||||
source: 'Source: Reporters Without Borders',
|
source: 'Source: Reporters Without Borders',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Sort"
|
name="Sort"
|
||||||
{...withStoryDocs(sortDocs)}
|
{...withStoryDocs(sortDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: pressFreedom,
|
data: pressFreedom,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'Score',
|
sortField: 'Score',
|
||||||
|
|
@ -145,13 +145,13 @@
|
||||||
title: 'Press Freedom Index',
|
title: 'Press Freedom Index',
|
||||||
notes: 'Note: data as of 2018',
|
notes: 'Note: data as of 2018',
|
||||||
source: 'Source: Reporters Without Borders',
|
source: 'Source: Reporters Without Borders',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Format"
|
name="Format"
|
||||||
{...withStoryDocs(formatDocs)}
|
{...withStoryDocs(formatDocs)}
|
||||||
args="{{
|
args={{
|
||||||
data: richestWomen,
|
data: richestWomen,
|
||||||
title: 'The Richest Women in the World',
|
title: 'The Richest Women in the World',
|
||||||
source: 'Source: Forbes',
|
source: 'Source: Forbes',
|
||||||
|
|
@ -159,16 +159,16 @@
|
||||||
sortField: 'Net worth (in billions)',
|
sortField: 'Net worth (in billions)',
|
||||||
sortDirection: 'descending',
|
sortDirection: 'descending',
|
||||||
fieldFormatters: { 'Net worth (in billions)': currencyFormat },
|
fieldFormatters: { 'Net worth (in billions)': currencyFormat },
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Style"
|
name="Style"
|
||||||
{...withStoryDocs(styleDocs)}
|
{...withStoryDocs(styleDocs)}
|
||||||
args="{{
|
args={{
|
||||||
id: 'custom-table',
|
id: 'custom-table',
|
||||||
data: richestWomen,
|
data: richestWomen,
|
||||||
title: 'The Richest Women in the World',
|
title: 'The Richest Women in the World',
|
||||||
source: 'Source: Forbes',
|
source: 'Source: Forbes',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -230,9 +230,9 @@
|
||||||
{#if filterList}
|
{#if filterList}
|
||||||
<div class="table--header--filter">
|
<div class="table--header--filter">
|
||||||
<Select
|
<Select
|
||||||
label="{filterLabel || filterField}"
|
label={filterLabel || filterField}
|
||||||
options="{filterList}"
|
options={filterList}
|
||||||
on:select="{handleFilterInput}"
|
on:select={handleFilterInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -240,7 +240,7 @@
|
||||||
<div class="table--header--search">
|
<div class="table--header--search">
|
||||||
<SearchInput
|
<SearchInput
|
||||||
bind:searchPlaceholder
|
bind:searchPlaceholder
|
||||||
on:search="{handleSearchInput}"
|
on:search={handleSearchInput}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -252,9 +252,7 @@
|
||||||
<table
|
<table
|
||||||
class="w-full"
|
class="w-full"
|
||||||
class:paginated
|
class:paginated
|
||||||
class:truncated="{truncated &&
|
class:truncated={truncated && !showAll && data.length > truncateLength}
|
||||||
!showAll &&
|
|
||||||
data.length > truncateLength}"
|
|
||||||
>
|
>
|
||||||
<thead class="table--thead">
|
<thead class="table--thead">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -262,22 +260,22 @@
|
||||||
<th
|
<th
|
||||||
scope="col"
|
scope="col"
|
||||||
class="table--thead--th h4 pl-0 py-2 pr-2"
|
class="table--thead--th h4 pl-0 py-2 pr-2"
|
||||||
class:sortable="{sortable && sortableFields.includes(field)}"
|
class:sortable={sortable && sortableFields.includes(field)}
|
||||||
class:sort-ascending="{sortable &&
|
class:sort-ascending={sortable &&
|
||||||
sortField === field &&
|
sortField === field &&
|
||||||
sortDirection === 'ascending'}"
|
sortDirection === 'ascending'}
|
||||||
class:sort-descending="{sortable &&
|
class:sort-descending={sortable &&
|
||||||
sortField === field &&
|
sortField === field &&
|
||||||
sortDirection === 'descending'}"
|
sortDirection === 'descending'}
|
||||||
data-field="{field}"
|
data-field={field}
|
||||||
on:click="{handleSort}"
|
on:click={handleSort}
|
||||||
>
|
>
|
||||||
{field}
|
{field}
|
||||||
{#if sortable && sortableFields.includes(field)}
|
{#if sortable && sortableFields.includes(field)}
|
||||||
<div class="table--thead--sortarrow fml-1 avoid-clicks">
|
<div class="table--thead--sortarrow fml-1 avoid-clicks">
|
||||||
<SortArrow
|
<SortArrow
|
||||||
bind:sortDirection
|
bind:sortDirection
|
||||||
active="{sortField === field}"
|
active={sortField === field}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -287,13 +285,13 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table--tbody">
|
<tbody class="table--tbody">
|
||||||
{#each currentPageData as item, idx}
|
{#each currentPageData as item, idx}
|
||||||
<tr data-row-index="{idx}">
|
<tr data-row-index={idx}>
|
||||||
{#each includedFields as field}
|
{#each includedFields as field}
|
||||||
<td
|
<td
|
||||||
class="body-note pl-0 py-2 pr-2"
|
class="body-note pl-0 py-2 pr-2"
|
||||||
data-row-index="{idx}"
|
data-row-index={idx}
|
||||||
data-field="{field}"
|
data-field={field}
|
||||||
data-value="{item[field]}"
|
data-value={item[field]}
|
||||||
>
|
>
|
||||||
{@html formatValue(item, field)}
|
{@html formatValue(item, field)}
|
||||||
</td>
|
</td>
|
||||||
|
|
@ -302,7 +300,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
{#if searchable && searchText && currentPageData.length === 0}
|
{#if searchable && searchText && currentPageData.length === 0}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="no-results" colspan="{includedFields.length}">
|
<td class="no-results" colspan={includedFields.length}>
|
||||||
No results found for "{searchText}"
|
No results found for "{searchText}"
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -312,7 +310,7 @@
|
||||||
<tfoot class="table--tfoot">
|
<tfoot class="table--tfoot">
|
||||||
{#if notes}
|
{#if notes}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="" colspan="{includedFields.length}">
|
<td class="" colspan={includedFields.length}>
|
||||||
<div class="fmt-2">
|
<div class="fmt-2">
|
||||||
{@html notes}
|
{@html notes}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -321,7 +319,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
{#if source}
|
{#if source}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="" colspan="{includedFields.length}">
|
<td class="" colspan={includedFields.length}>
|
||||||
<div class="fmt-1">
|
<div class="fmt-1">
|
||||||
{@html source}
|
{@html source}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -337,7 +335,7 @@
|
||||||
aria-label="Show all button"
|
aria-label="Show all button"
|
||||||
class="show-all flex items-center justify-center fmt-2"
|
class="show-all flex items-center justify-center fmt-2"
|
||||||
>
|
>
|
||||||
<button class="body-caption" on:click="{toggleTruncate}"
|
<button class="body-caption" on:click={toggleTruncate}
|
||||||
>{#if showAll}Show fewer rows{:else}Show {data.length -
|
>{#if showAll}Show fewer rows{:else}Show {data.length -
|
||||||
truncateLength} more rows{/if}</button
|
truncateLength} more rows{/if}</button
|
||||||
>
|
>
|
||||||
|
|
@ -347,8 +345,8 @@
|
||||||
<Pagination
|
<Pagination
|
||||||
bind:pageNumber
|
bind:pageNumber
|
||||||
bind:pageSize
|
bind:pageSize
|
||||||
bind:pageLength="{currentPageData.length}"
|
bind:pageLength={currentPageData.length}
|
||||||
bind:n="{sortedData.length}"
|
bind:n={sortedData.length}
|
||||||
/>{/if}
|
/>{/if}
|
||||||
</article>
|
</article>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
import SharkImg from './stories/shark.jpg';
|
import SharkImg from './stories/shark.jpg';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ ...args })}
|
{#snippet children({ ...args })}
|
||||||
<TestForSvelte5 {...args} />
|
<TestForSvelte5 {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -36,9 +36,9 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
src: SharkImg,
|
src: SharkImg,
|
||||||
altText: "Duh dum! It's a shark!!",
|
altText: "Duh dum! It's a shark!!",
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@
|
||||||
|
|
||||||
<Block {width} {id} class="photo {cls}">
|
<Block {width} {id} class="photo {cls}">
|
||||||
<div
|
<div
|
||||||
style:background-image="{`url(${src})`}"
|
style:background-image={`url(${src})`}
|
||||||
style:height="{`${height}px`}"
|
style:height={`${height}px`}
|
||||||
></div>
|
></div>
|
||||||
<p class="visually-hidden">{altText}</p>
|
<p class="visually-hidden">{altText}</p>
|
||||||
</Block>
|
</Block>
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
import Headline from './../Headline/Headline.svelte';
|
import Headline from './../Headline/Headline.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<div class="reset-article">
|
<div class="reset-article">
|
||||||
<Theme {...args}>
|
<Theme {...args}>
|
||||||
|
|
@ -52,19 +52,19 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
theme: themes.light,
|
theme: themes.light,
|
||||||
base: 'light',
|
base: 'light',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story name="Custom theme" {...withStoryDocs(customiseDocs)}>
|
<Story name="Custom theme" {...withStoryDocs(customiseDocs)}>
|
||||||
<Theme
|
<Theme
|
||||||
base="dark"
|
base="dark"
|
||||||
theme="{{
|
theme={{
|
||||||
colour: { accent: 'var(--tr-light-orange)' },
|
colour: { accent: 'var(--tr-light-orange)' },
|
||||||
font: { family: { hed: 'FreightText, serif' } },
|
font: { family: { hed: 'FreightText, serif' } },
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<ThemedPage />
|
<ThemedPage />
|
||||||
</Theme>
|
</Theme>
|
||||||
|
|
@ -73,15 +73,15 @@
|
||||||
<Story name="Custom Google font" {...withStoryDocs(customiseFontDocs)}>
|
<Story name="Custom Google font" {...withStoryDocs(customiseFontDocs)}>
|
||||||
<Theme
|
<Theme
|
||||||
base="light"
|
base="light"
|
||||||
theme="{{
|
theme={{
|
||||||
font: { family: { hed: 'Bebas Neue, sans-serif' } },
|
font: { family: { hed: 'Bebas Neue, sans-serif' } },
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<div class="gfont">
|
<div class="gfont">
|
||||||
<Headline
|
<Headline
|
||||||
hed="{'Reuters Graphics Interactive'}"
|
hed={'Reuters Graphics Interactive'}
|
||||||
dek="{'The beginning of a beautiful page'}"
|
dek={'The beginning of a beautiful page'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Theme>
|
</Theme>
|
||||||
|
|
@ -91,9 +91,9 @@
|
||||||
<div id="pattern-bg">
|
<div id="pattern-bg">
|
||||||
<Theme
|
<Theme
|
||||||
base="dark"
|
base="dark"
|
||||||
theme="{{
|
theme={{
|
||||||
colour: { background: 'transparent' },
|
colour: { background: 'transparent' },
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
<SiteHeader />
|
<SiteHeader />
|
||||||
<ThemedPage />
|
<ThemedPage />
|
||||||
|
|
@ -102,22 +102,22 @@
|
||||||
</Story>
|
</Story>
|
||||||
|
|
||||||
<Story name="Inheritance" {...withStoryDocs(inheritanceDocs)}>
|
<Story name="Inheritance" {...withStoryDocs(inheritanceDocs)}>
|
||||||
<Theme theme="{themes.light}">
|
<Theme theme={themes.light}>
|
||||||
<div class="themed">
|
<div class="themed">
|
||||||
<p>Theme</p>
|
<p>Theme</p>
|
||||||
<Theme theme="{themes.dark}">
|
<Theme theme={themes.dark}>
|
||||||
<div class="themed">
|
<div class="themed">
|
||||||
<p>Sub-theme</p>
|
<p>Sub-theme</p>
|
||||||
<Theme theme="{themes.light}">
|
<Theme theme={themes.light}>
|
||||||
<div class="themed">
|
<div class="themed">
|
||||||
<p>Sub-sub</p>
|
<p>Sub-sub</p>
|
||||||
</div>
|
</div>
|
||||||
</Theme>
|
</Theme>
|
||||||
<Theme
|
<Theme
|
||||||
theme="{{
|
theme={{
|
||||||
colour: { background: 'steelblue', 'text-primary': '#fff' },
|
colour: { background: 'steelblue', 'text-primary': '#fff' },
|
||||||
font: { family: { note: 'FreightText, serif' } },
|
font: { family: { note: 'FreightText, serif' } },
|
||||||
}}"
|
}}
|
||||||
base="dark"
|
base="dark"
|
||||||
>
|
>
|
||||||
<div class="themed">
|
<div class="themed">
|
||||||
|
|
|
||||||
|
|
@ -11,23 +11,21 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { CustomTheme } from './@types/component';
|
import type { CustomTheme } from './@types/component';
|
||||||
|
|
||||||
|
|
||||||
type Base = 'light' | 'dark';
|
type Base = 'light' | 'dark';
|
||||||
|
|
||||||
|
|
||||||
import flatten from './utils/flatten';
|
import flatten from './utils/flatten';
|
||||||
import mergeThemes from './utils/merge';
|
import mergeThemes from './utils/merge';
|
||||||
interface Props {
|
interface Props {
|
||||||
/** Custom theme object. Can be a partial theme with just
|
/** Custom theme object. Can be a partial theme with just
|
||||||
* what you want to change.
|
* what you want to change.
|
||||||
*/
|
*/
|
||||||
theme?: CustomTheme;
|
theme?: CustomTheme;
|
||||||
/**
|
/**
|
||||||
* Base theme is one of `light` or `dark` and will be merged
|
* Base theme is one of `light` or `dark` and will be merged
|
||||||
* with your custom theme to fill in any values you don't
|
* with your custom theme to fill in any values you don't
|
||||||
* explicitly set.
|
* explicitly set.
|
||||||
*/
|
*/
|
||||||
base?: Base;
|
base?: Base;
|
||||||
children?: import('svelte').Snippet;
|
children?: import('svelte').Snippet;
|
||||||
}
|
}
|
||||||
|
|
@ -35,14 +33,18 @@
|
||||||
let { theme = {}, base = 'light', children }: Props = $props();
|
let { theme = {}, base = 'light', children }: Props = $props();
|
||||||
|
|
||||||
/** @type {Theme} */
|
/** @type {Theme} */
|
||||||
let mergedTheme = $derived(mergeThemes({}, themes[base] || themes.light, theme));
|
let mergedTheme = $derived(
|
||||||
|
mergeThemes({}, themes[base] || themes.light, theme)
|
||||||
|
);
|
||||||
|
|
||||||
let cssVariables = $derived(Object.entries(flatten({ theme: mergedTheme }))
|
let cssVariables = $derived(
|
||||||
.map(([key, value]) => `--${key}: ${value};`)
|
Object.entries(flatten({ theme: mergedTheme }))
|
||||||
.join(' '));
|
.map(([key, value]) => `--${key}: ${value};`)
|
||||||
|
.join(' ')
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="theme" style="{cssVariables}" style:display="contents">
|
<div class="theme" style={cssVariables} style:display="contents">
|
||||||
<!-- Clients can override the theme above by attaching custom properties to this element. -->
|
<!-- Clients can override the theme above by attaching custom properties to this element. -->
|
||||||
<div class="theme-client-override" style="display: contents;">
|
<div class="theme-client-override" style="display: contents;">
|
||||||
<!-- Themed content -->
|
<!-- Themed content -->
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,21 @@
|
||||||
|
|
||||||
<Article>
|
<Article>
|
||||||
<Headline
|
<Headline
|
||||||
hed="{'Reuters Graphics Interactive'}"
|
hed={'Reuters Graphics Interactive'}
|
||||||
dek="{'The beginning of a beautiful page'}"
|
dek={'The beginning of a beautiful page'}
|
||||||
section="{'Global news'}"
|
section={'Global news'}
|
||||||
authors="{['Jon McClure', 'Prasanta Kumar Dutta']}"
|
authors={['Jon McClure', 'Prasanta Kumar Dutta']}
|
||||||
publishTime="{new Date('2021-09-12').toISOString()}"
|
publishTime={new Date('2021-09-12').toISOString()}
|
||||||
/>
|
/>
|
||||||
<BodyText
|
<BodyText
|
||||||
text="{`Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.
|
text={`Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.
|
||||||
|
|
||||||
Prosciutto kevin brisket sirloin pork loin shoulder cupim sausage chicken jowl strip steak rump pork ball tip ham hock. Swine pork belly fatback alcatra jowl.
|
Prosciutto kevin brisket sirloin pork loin shoulder cupim sausage chicken jowl strip steak rump pork ball tip ham hock. Swine pork belly fatback alcatra jowl.
|
||||||
|
|
||||||
## Brisket sirloin
|
## Brisket sirloin
|
||||||
|
|
||||||
Shank strip steak turkey shoulder shankle leberkas pork chop, t-bone picanha buffalo ground round burgdoggen ribeye.
|
Shank strip steak turkey shoulder shankle leberkas pork chop, t-bone picanha buffalo ground round burgdoggen ribeye.
|
||||||
`}"
|
`}
|
||||||
/>
|
/>
|
||||||
<GraphicBlock
|
<GraphicBlock
|
||||||
title="Steak tar-tar"
|
title="Steak tar-tar"
|
||||||
|
|
@ -31,7 +31,7 @@ Shank strip steak turkey shoulder shankle leberkas pork chop, t-bone picanha buf
|
||||||
<div class="fake-graphic"></div>
|
<div class="fake-graphic"></div>
|
||||||
</GraphicBlock>
|
</GraphicBlock>
|
||||||
<BodyText
|
<BodyText
|
||||||
text="{'Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.'}"
|
text={'Bacon ipsum dolor amet cupim porchetta chuck buffalo sirloin beef. Biltong ham brisket tenderloin hamburger doner.'}
|
||||||
/>
|
/>
|
||||||
</Article>
|
</Article>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<div>
|
<div>
|
||||||
<ToolsHeader {...args} />
|
<ToolsHeader {...args} />
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Template>
|
</Template>
|
||||||
|
|
||||||
<Story name="Default" args="{{}}" />
|
<Story name="Default" args={{}} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div {
|
div {
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@
|
||||||
|
|
||||||
<header
|
<header
|
||||||
{id}
|
{id}
|
||||||
class="{cls}"
|
class={cls}
|
||||||
class:sticky
|
class:sticky
|
||||||
style:background
|
style:background
|
||||||
style:border-bottom="{borderBottom}"
|
style:border-bottom={borderBottom}
|
||||||
>
|
>
|
||||||
<div class="logo-container">
|
<div class="logo-container">
|
||||||
<a href="{homeLink}">
|
<a href={homeLink}>
|
||||||
<ReutersGraphicsLogo {...{ ...logoProps, ...{ width: '100%' } }} />
|
<ReutersGraphicsLogo {...{ ...logoProps, ...{ width: '100%' } }} />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onclick="{forwardBtnClick}"
|
onclick={forwardBtnClick}
|
||||||
style="
|
style="
|
||||||
opacity: {controlsOpacity};
|
opacity: {controlsOpacity};
|
||||||
top: {controlsPosition === 'top left' || controlsPosition === 'top right' ?
|
top: {controlsPosition === 'top left' || controlsPosition === 'top right' ?
|
||||||
|
|
@ -50,18 +50,18 @@
|
||||||
{#if resetCondition}
|
{#if resetCondition}
|
||||||
<i class="play-pause-icon replay">
|
<i class="play-pause-icon replay">
|
||||||
{#if separateReplayIcon}
|
{#if separateReplayIcon}
|
||||||
<Fa icon="{faReply}" size="2x" color="{controlsColour}" />
|
<Fa icon={faReply} size="2x" color={controlsColour} />
|
||||||
{:else}
|
{:else}
|
||||||
<Fa icon="{faPlay}" size="2x" color="{controlsColour}" />
|
<Fa icon={faPlay} size="2x" color={controlsColour} />
|
||||||
{/if}
|
{/if}
|
||||||
</i>
|
</i>
|
||||||
{:else if paused === false}
|
{:else if paused === false}
|
||||||
<i class="play-pause-icon pause">
|
<i class="play-pause-icon pause">
|
||||||
<Fa icon="{faPause}" size="2x" color="{controlsColour}" />
|
<Fa icon={faPause} size="2x" color={controlsColour} />
|
||||||
</i>
|
</i>
|
||||||
{:else if paused === true}
|
{:else if paused === true}
|
||||||
<i class="play-pause-icon play">
|
<i class="play-pause-icon play">
|
||||||
<Fa icon="{faPlay}" size="2x" color="{controlsColour}" />
|
<Fa icon={faPlay} size="2x" color={controlsColour} />
|
||||||
</i>
|
</i>
|
||||||
{:else}
|
{:else}
|
||||||
error
|
error
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
import SoundVideo from './stories/videos/sound-video.mp4';
|
import SoundVideo from './stories/videos/sound-video.mp4';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Video {...args} />
|
<Video {...args} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
@ -39,17 +39,17 @@
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
ariaDescription: 'Compulsory description of your video for screen readers.',
|
ariaDescription: 'Compulsory description of your video for screen readers.',
|
||||||
src: SilentVideo,
|
src: SilentVideo,
|
||||||
width: 'wide',
|
width: 'wide',
|
||||||
notes: 'Optional caption for your video.',
|
notes: 'Optional caption for your video.',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Playing and looping"
|
name="Playing and looping"
|
||||||
args="{{
|
args={{
|
||||||
ariaDescription: 'Compulsory description of your video for screen readers.',
|
ariaDescription: 'Compulsory description of your video for screen readers.',
|
||||||
src: SilentVideo,
|
src: SilentVideo,
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
|
|
@ -57,13 +57,13 @@
|
||||||
notes:
|
notes:
|
||||||
"World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters",
|
"World's longest glass bridge opens to public in Vietnam. (c) 2022 Thomson Reuters",
|
||||||
playVideoThreshold: 0.9,
|
playVideoThreshold: 0.9,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(playAndLoopDocs)}
|
{...withStoryDocs(playAndLoopDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Controls"
|
name="Controls"
|
||||||
args="{{
|
args={{
|
||||||
ariaDescription: 'Compulsory description of your video for screen readers.',
|
ariaDescription: 'Compulsory description of your video for screen readers.',
|
||||||
src: SilentVideo,
|
src: SilentVideo,
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
|
|
@ -76,13 +76,13 @@
|
||||||
separateReplayIcon: true,
|
separateReplayIcon: true,
|
||||||
loopVideo: false,
|
loopVideo: false,
|
||||||
hoverToSeeControls: true,
|
hoverToSeeControls: true,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(controlsDocs)}
|
{...withStoryDocs(controlsDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Videos with sound"
|
name="Videos with sound"
|
||||||
args="{{
|
args={{
|
||||||
ariaDescription: 'Compulsory description of your video for screen readers.',
|
ariaDescription: 'Compulsory description of your video for screen readers.',
|
||||||
src: SoundVideo,
|
src: SoundVideo,
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
|
|
@ -94,6 +94,6 @@
|
||||||
muteVideo: false,
|
muteVideo: false,
|
||||||
playVideoWhenInView: true,
|
playVideoWhenInView: true,
|
||||||
allowSoundToAutoplay: true,
|
allowSoundToAutoplay: true,
|
||||||
}}"
|
}}
|
||||||
{...withStoryDocs(controlsDocs)}
|
{...withStoryDocs(controlsDocs)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -165,8 +165,8 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window
|
<svelte:window
|
||||||
on:click="{setInteractedWithDom}"
|
on:click={setInteractedWithDom}
|
||||||
on:touchstart="{setInteractedWithDom}"
|
on:touchstart={setInteractedWithDom}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<GraphicBlock
|
<GraphicBlock
|
||||||
|
|
@ -179,18 +179,18 @@
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
role="figure"
|
role="figure"
|
||||||
on:mouseover="{() => {
|
on:mouseover={() => {
|
||||||
interactiveControlsOpacity = controlsOpacity;
|
interactiveControlsOpacity = controlsOpacity;
|
||||||
}}"
|
}}
|
||||||
on:focus="{() => {
|
on:focus={() => {
|
||||||
interactiveControlsOpacity = controlsOpacity;
|
interactiveControlsOpacity = controlsOpacity;
|
||||||
}}"
|
}}
|
||||||
on:mouseout="{() => {
|
on:mouseout={() => {
|
||||||
interactiveControlsOpacity = 0;
|
interactiveControlsOpacity = 0;
|
||||||
}}"
|
}}
|
||||||
on:blur="{() => {
|
on:blur={() => {
|
||||||
interactiveControlsOpacity = 0;
|
interactiveControlsOpacity = 0;
|
||||||
}}"
|
}}
|
||||||
>
|
>
|
||||||
{#if (hidden && ariaDescription) || !hidden}
|
{#if (hidden && ariaDescription) || !hidden}
|
||||||
{#if ariaDescription}
|
{#if ariaDescription}
|
||||||
|
|
@ -202,25 +202,25 @@
|
||||||
<IntersectionObserver
|
<IntersectionObserver
|
||||||
{element}
|
{element}
|
||||||
bind:intersecting
|
bind:intersecting
|
||||||
threshold="{playVideoThreshold}"
|
threshold={playVideoThreshold}
|
||||||
once="{false}"
|
once={false}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
bind:this="{element}"
|
bind:this={element}
|
||||||
class="video-wrapper relative block"
|
class="video-wrapper relative block"
|
||||||
aria-hidden="{hidden}"
|
aria-hidden={hidden}
|
||||||
bind:clientWidth="{widthVideoContainer}"
|
bind:clientWidth={widthVideoContainer}
|
||||||
bind:clientHeight="{heightVideoContainer}"
|
bind:clientHeight={heightVideoContainer}
|
||||||
>
|
>
|
||||||
{#if possibleToPlayPause}
|
{#if possibleToPlayPause}
|
||||||
{#if showControls}
|
{#if showControls}
|
||||||
<Controls
|
<Controls
|
||||||
on:pausePlayEvent="{pausePlayEvent}"
|
on:pausePlayEvent={pausePlayEvent}
|
||||||
{paused}
|
{paused}
|
||||||
{clickedOnPauseBtn}
|
{clickedOnPauseBtn}
|
||||||
controlsOpacity="{hoverToSeeControls ?
|
controlsOpacity={hoverToSeeControls ?
|
||||||
interactiveControlsOpacity
|
interactiveControlsOpacity
|
||||||
: controlsOpacity}"
|
: controlsOpacity}
|
||||||
{controlsPosition}
|
{controlsPosition}
|
||||||
{widthVideoContainer}
|
{widthVideoContainer}
|
||||||
{heightVideoContainer}
|
{heightVideoContainer}
|
||||||
|
|
@ -232,32 +232,32 @@
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
class="border-0 m-0 p-0 bg-transparent absolute"
|
class="border-0 m-0 p-0 bg-transparent absolute"
|
||||||
on:click="{() => {
|
on:click={() => {
|
||||||
if (paused === true) {
|
if (paused === true) {
|
||||||
paused = false;
|
paused = false;
|
||||||
} else {
|
} else {
|
||||||
paused = true;
|
paused = true;
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
||||||
></button>
|
></button>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<video
|
<video
|
||||||
bind:this="{videoElement}"
|
bind:this={videoElement}
|
||||||
{src}
|
{src}
|
||||||
{poster}
|
{poster}
|
||||||
class="pointer-events-none relative"
|
class="pointer-events-none relative"
|
||||||
width="100%"
|
width="100%"
|
||||||
muted="{muteVideo}"
|
muted={muteVideo}
|
||||||
playsinline
|
playsinline
|
||||||
preload="{preloadVideo}"
|
preload={preloadVideo}
|
||||||
loop="{loopVideo}"
|
loop={loopVideo}
|
||||||
bind:currentTime="{time}"
|
bind:currentTime={time}
|
||||||
bind:duration
|
bind:duration
|
||||||
bind:paused
|
bind:paused
|
||||||
bind:clientWidth="{widthVideo}"
|
bind:clientWidth={widthVideo}
|
||||||
bind:clientHeight="{heightVideo}"
|
bind:clientHeight={heightVideo}
|
||||||
>
|
>
|
||||||
<track kind="captions" />
|
<track kind="captions" />
|
||||||
</video>
|
</video>
|
||||||
|
|
@ -267,14 +267,14 @@
|
||||||
<!-- Video element without Intersection observer -->
|
<!-- Video element without Intersection observer -->
|
||||||
<div
|
<div
|
||||||
class="video-wrapper relative"
|
class="video-wrapper relative"
|
||||||
aria-hidden="{hidden}"
|
aria-hidden={hidden}
|
||||||
bind:clientWidth="{widthVideoContainer}"
|
bind:clientWidth={widthVideoContainer}
|
||||||
bind:clientHeight="{heightVideoContainer}"
|
bind:clientHeight={heightVideoContainer}
|
||||||
>
|
>
|
||||||
{#if possibleToPlayPause}
|
{#if possibleToPlayPause}
|
||||||
{#if showControls}
|
{#if showControls}
|
||||||
<Controls
|
<Controls
|
||||||
on:pausePlayEvent="{pausePlayEvent}"
|
on:pausePlayEvent={pausePlayEvent}
|
||||||
{paused}
|
{paused}
|
||||||
{clickedOnPauseBtn}
|
{clickedOnPauseBtn}
|
||||||
{controlsOpacity}
|
{controlsOpacity}
|
||||||
|
|
@ -289,33 +289,33 @@
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
class="border-0 m-0 p-0 bg-transparent absolute"
|
class="border-0 m-0 p-0 bg-transparent absolute"
|
||||||
on:click="{() => {
|
on:click={() => {
|
||||||
if (paused === true) {
|
if (paused === true) {
|
||||||
paused = false;
|
paused = false;
|
||||||
} else {
|
} else {
|
||||||
paused = true;
|
paused = true;
|
||||||
}
|
}
|
||||||
}}"
|
}}
|
||||||
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
style="top: 0; left: 0; width: {widthVideoContainer}px; height: {heightVideoContainer}px;"
|
||||||
></button>
|
></button>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<video
|
<video
|
||||||
bind:this="{videoElement}"
|
bind:this={videoElement}
|
||||||
{src}
|
{src}
|
||||||
{poster}
|
{poster}
|
||||||
class="pointer-events-none relative"
|
class="pointer-events-none relative"
|
||||||
width="100%"
|
width="100%"
|
||||||
muted="{muteVideo}"
|
muted={muteVideo}
|
||||||
playsinline
|
playsinline
|
||||||
preload="{preloadVideo}"
|
preload={preloadVideo}
|
||||||
loop="{loopVideo}"
|
loop={loopVideo}
|
||||||
bind:currentTime="{time}"
|
bind:currentTime={time}
|
||||||
bind:duration
|
bind:duration
|
||||||
bind:paused
|
bind:paused
|
||||||
autoplay
|
autoplay
|
||||||
bind:clientWidth="{widthVideo}"
|
bind:clientWidth={widthVideo}
|
||||||
bind:clientHeight="{heightVideo}"
|
bind:clientHeight={heightVideo}
|
||||||
>
|
>
|
||||||
<track kind="captions" />
|
<track kind="captions" />
|
||||||
</video>
|
</video>
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,16 @@
|
||||||
import { Template, Story } from '@storybook/addon-svelte-csf';
|
import { Template, Story } from '@storybook/addon-svelte-csf';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Template >
|
<Template>
|
||||||
{#snippet children({ args })}
|
{#snippet children({ args })}
|
||||||
<Visible {...args} >
|
<Visible {...args}>
|
||||||
{#snippet children({ visible })}
|
{#snippet children({ visible })}
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<p>Visible!</p>
|
<p>Visible!</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p>Not yet visible.</p>
|
<p>Not yet visible.</p>
|
||||||
{/if}
|
{/if}
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Visible>
|
</Visible>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Template>
|
</Template>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
<!-- @component `Visible` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-utilities-visible--docs) -->
|
<!-- @component `Visible` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-utilities-visible--docs) -->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
/**
|
/**
|
||||||
* Whether to change visibility just once.
|
* Whether to change visibility just once.
|
||||||
*
|
*
|
||||||
* Useful for loading expensive images or other media and then keeping them around once they're first loaded.
|
* Useful for loading expensive images or other media and then keeping them around once they're first loaded.
|
||||||
*/
|
*/
|
||||||
once?: boolean;
|
once?: boolean;
|
||||||
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top`. */
|
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top`. */
|
||||||
top?: number;
|
top?: number;
|
||||||
|
|
@ -34,7 +29,7 @@
|
||||||
left = 0,
|
left = 0,
|
||||||
right = 0,
|
right = 0,
|
||||||
threshold = 0,
|
threshold = 0,
|
||||||
children
|
children,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let visible = $state(false);
|
let visible = $state(false);
|
||||||
|
|
@ -74,7 +69,7 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this="{container}">
|
<div bind:this={container}>
|
||||||
<!-- An element or component -->
|
<!-- An element or component -->
|
||||||
{@render children?.({ visible, })}
|
{@render children?.({ visible })}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { Visible } from '@reuters-graphics/graphics-components';
|
import { Visible } from '@reuters-graphics/graphics-components';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Visible >
|
<Visible>
|
||||||
{#snippet children({ visible })}
|
{#snippet children({ visible })}
|
||||||
{#if visible}
|
{#if visible}
|
||||||
<p>Visible!</p>
|
<p>Visible!</p>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ Once you've setup the `Meta` and `Template` components as below, you can write a
|
||||||
import YourComponent from './YourComponent.svelte';
|
import YourComponent from './YourComponent.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Meta title="Components/YourComponent" component="{YourComponent}" />
|
<Meta title="Components/YourComponent" component={YourComponent} />
|
||||||
|
|
||||||
<Template let:args>
|
<Template let:args>
|
||||||
<YourComponent {...args} />
|
<YourComponent {...args} />
|
||||||
|
|
@ -28,9 +28,9 @@ Once you've setup the `Meta` and `Template` components as below, you can write a
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -47,16 +47,16 @@ You can define additional stories with _different_ args to show how your compone
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Default"
|
name="Default"
|
||||||
args="{{
|
args={{
|
||||||
width: 'normal',
|
width: 'normal',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Extra wide"
|
name="Extra wide"
|
||||||
args="{{
|
args={{
|
||||||
width: 'wider',
|
width: 'wider',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -66,10 +66,10 @@ If you want even more control, you can skip the `args` and pass your component d
|
||||||
<Story name="Super custom">
|
<Story name="Super custom">
|
||||||
<YourComponent
|
<YourComponent
|
||||||
width="fluid"
|
width="fluid"
|
||||||
data="{[
|
data={[
|
||||||
{ id: 'UK', value: 65 },
|
{ id: 'UK', value: 65 },
|
||||||
{ id: 'USA', value: 265 },
|
{ id: 'USA', value: 265 },
|
||||||
]}"
|
]}
|
||||||
/>
|
/>
|
||||||
</Story>
|
</Story>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ You can customise the controls in Storybook's built-in [controls panel](https://
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Meta title="Components/YourComponent" component="{YourComponent}" {...meta} />
|
<Meta title="Components/YourComponent" component={YourComponent} {...meta} />
|
||||||
|
|
||||||
<template let:args>
|
<template let:args>
|
||||||
<YourComponent {...args} />
|
<YourComponent {...args} />
|
||||||
|
|
|
||||||
|
|
@ -47,19 +47,19 @@ Now, import your markdown file in your story page component and attach it to eit
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Meta title="Components/YourComponent" component="{YourComponent}" {...meta} />
|
<Meta title="Components/YourComponent" component={YourComponent} {...meta} />
|
||||||
|
|
||||||
<template let:args>
|
<template let:args>
|
||||||
<YourComponent {...args} />
|
<YourComponent {...args} />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- The first story will use the component docs in Meta... -->
|
<!-- The first story will use the component docs in Meta... -->
|
||||||
<Story name="Basic" args="{{ width: 'normal' }}" />
|
<Story name="Basic" args={{ width: 'normal' }} />
|
||||||
|
|
||||||
<!-- Additional stories can use other docs now. -->
|
<!-- Additional stories can use other docs now. -->
|
||||||
<Story
|
<Story
|
||||||
name="Another story"
|
name="Another story"
|
||||||
args="{{ width: 'normal' }}"
|
args={{ width: 'normal' }}
|
||||||
{...withStoryDocs(someStoryDocs)}
|
{...withStoryDocs(someStoryDocs)}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
@ -110,7 +110,7 @@ Now, import your snippet file in your story page component and attach it to any
|
||||||
<!-- Pass source in inside an object keyed by your snippet's language, e.g., svelte, scss, etc. -->
|
<!-- Pass source in inside an object keyed by your snippet's language, e.g., svelte, scss, etc. -->
|
||||||
<Story
|
<Story
|
||||||
name="Basic"
|
name="Basic"
|
||||||
args="{{ width: 'normal' }}"
|
args={{ width: 'normal' }}
|
||||||
{...withSource({ svelte: defaultSnippet })}
|
{...withSource({ svelte: defaultSnippet })}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
@ -124,7 +124,7 @@ If you're adding source code AND custom docs to a story, you can chain `withSour
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Extra wide"
|
name="Extra wide"
|
||||||
args="{{ width: 'wider' }}"
|
args={{ width: 'wider' }}
|
||||||
{...withComponentDocs(componentDocs, withSource({ svelte: defaultSnippet }))}
|
{...withComponentDocs(componentDocs, withSource({ svelte: defaultSnippet }))}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ Now, import your media file directly in your code, which will resolve to the URL
|
||||||
import myImageSrc from './stories/imgs/myImage.jpg';
|
import myImageSrc from './stories/imgs/myImage.jpg';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Meta title="Components/YourComponent" component="{YourComponent}" />
|
<Meta title="Components/YourComponent" component={YourComponent} />
|
||||||
|
|
||||||
<template let:args>
|
<template let:args>
|
||||||
<YourComponent {...args} />
|
<YourComponent {...args} />
|
||||||
|
|
@ -42,9 +42,9 @@ Now, import your media file directly in your code, which will resolve to the URL
|
||||||
|
|
||||||
<Story
|
<Story
|
||||||
name="Basic"
|
name="Basic"
|
||||||
args="{{
|
args={{
|
||||||
src: myImageSrc,
|
src: myImageSrc,
|
||||||
altText: 'My image in the component',
|
altText: 'My image in the component',
|
||||||
}}"
|
}}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ Let's look at a basic component, a `ProfileCard`, with a demo that looks like th
|
||||||
|
|
||||||
<ProfileCard
|
<ProfileCard
|
||||||
name="Kitty"
|
name="Kitty"
|
||||||
age="{2}"
|
age={2}
|
||||||
img="https://cats.com/cat1.jpg"
|
img="https://cats.com/cat1.jpg"
|
||||||
birthday="{new Date('2020-09-25')}"
|
birthday={new Date('2020-09-25')}
|
||||||
bio="Some notes.\n\nWith multiple paragraphs."
|
bio="Some notes.\n\nWith multiple paragraphs."
|
||||||
isGood="{true}"
|
isGood={true}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -100,12 +100,12 @@ Notice all the values in the data are **strings**. More on that soon.
|
||||||
<!-- ... -->
|
<!-- ... -->
|
||||||
{:else if block.type === 'profile-card'}
|
{:else if block.type === 'profile-card'}
|
||||||
<ProfileCard
|
<ProfileCard
|
||||||
name="{block.name}"
|
name={block.name}
|
||||||
age="{parseInt(block.age)}"
|
age={parseInt(block.age)}
|
||||||
img="{`${assets}/${block.picture}`}"
|
img={`${assets}/${block.picture}`}
|
||||||
birthday="{new Date(block.birthday)}"
|
birthday={new Date(block.birthday)}
|
||||||
bio="{block.bio}"
|
bio={block.bio}
|
||||||
isGood="{block.isGood === 'true'}"
|
isGood={block.isGood === 'true'}
|
||||||
/>
|
/>
|
||||||
<!-- ... -->
|
<!-- ... -->
|
||||||
{/if}
|
{/if}
|
||||||
|
|
@ -136,12 +136,12 @@ Once we've identified we have the right block for our component, we need to conv
|
||||||
|
|
||||||
```svelte
|
```svelte
|
||||||
<ProfileCard
|
<ProfileCard
|
||||||
name="{block.name}"
|
name={block.name}
|
||||||
age="{parseInt(block.age)}"
|
age={parseInt(block.age)}
|
||||||
img="{`${assets}/${block.picture}`}"
|
img={`${assets}/${block.picture}`}
|
||||||
birthday="{new Date(block.birthday)}"
|
birthday={new Date(block.birthday)}
|
||||||
bio="{block.bio}"
|
bio={block.bio}
|
||||||
isGood="{block.isGood === 'true'}"
|
isGood={block.isGood === 'true'}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -191,7 +191,7 @@ Let's look at another example component:
|
||||||
```svelte
|
```svelte
|
||||||
<Timeline
|
<Timeline
|
||||||
title="A brief history of BitCoin"
|
title="A brief history of BitCoin"
|
||||||
dates="{[
|
dates={[
|
||||||
{
|
{
|
||||||
date: new Date('1992-01-01'),
|
date: new Date('1992-01-01'),
|
||||||
subhed:
|
subhed:
|
||||||
|
|
@ -208,7 +208,7 @@ Let's look at another example component:
|
||||||
subhed: 'The Winklevoss twins buy in',
|
subhed: 'The Winklevoss twins buy in',
|
||||||
img: `${assets}/images/winkle-boys.jpeg`,
|
img: `${assets}/images/winkle-boys.jpeg`,
|
||||||
},
|
},
|
||||||
]}"
|
]}
|
||||||
/>
|
/>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,5 +30,5 @@ In the Graphics Kit, that means you'll need to prefix relative paths with the sp
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Use the assets module to prefix the path to your image. -->
|
<!-- Use the assets module to prefix the path to your image. -->
|
||||||
<FeautrePhoto src="{`${assets}/imgs/myImage.jpg`}" />
|
<FeautrePhoto src={`${assets}/imgs/myImage.jpg`} />
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ A component is usually composed of several parts: JavaScript for managing data,
|
||||||
|
|
||||||
<!-- HTML -->
|
<!-- HTML -->
|
||||||
<figure>
|
<figure>
|
||||||
<img src="{imgSrc}" alt="{altText}" />
|
<img src={imgSrc} alt={altText} />
|
||||||
<figcaption>{caption}</figcaption>
|
<figcaption>{caption}</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,5 +32,5 @@ pnpm i @reuters-graphics/graphics-components
|
||||||
import { BodyText } from '@reuters-graphics/graphics-components';
|
import { BodyText } from '@reuters-graphics/graphics-components';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<BodyText text="{'Hello world!'}" />
|
<BodyText text={'Hello world!'} />
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue