migrates to svelte 5

This commit is contained in:
MinamiFunakoshiTR 2025-03-24 14:46:25 -07:00
parent 740db10d7b
commit 8cf1b1b552
Failed to extract signature
3 changed files with 95 additions and 82 deletions

View file

@ -6,25 +6,31 @@ import * as ReferralBlockStories from './ReferralBlock.stories.svelte';
# ReferralBlock # ReferralBlock
The `ReferralBlock` component creates a set of referral links from recent dotcom stories using the [recent stories by section API](https://www.reuters.com/pf/api/v3/content/fetch/recent-stories-by-sections-v1?query=%7B%22section_ids%22%3A%22%2Fworld%2F%22%2C%22size%22%3A20%2C%22website%22%3A%22reuters%22%7D) or the [articles by collection API](https://www.reuters.com/pf/api/v3/content/fetch/articles-by-collection-alias-or-id-v1?query=%7B%22collection_alias%22%3A%22x-trump%22%2C%22size%22%3A20%2C%22website%22%3A%22reuters%22%7D). The `ReferralBlock` component creates a set of referral links from recent Reuters.com stories using the [recent stories by section API](https://www.reuters.com/pf/api/v3/content/fetch/recent-stories-by-sections-v1?query=%7B%22section_ids%22%3A%22%2Fworld%2F%22%2C%22size%22%3A20%2C%22website%22%3A%22reuters%22%7D).
> The `section` or `collection` prop determines which section or collection stories are from. > Note: The `section` or `collection` prop determines which section or collection stories are from.
> >
> You can get the section ID from the section page on dotcom. For example, the section ID for World - Europe stories at `www.reuters.com/world/europe/` would be `/world/europe/`. (The leading and trailing slashes are required!) > You can get the section ID from the URL for the Reuters.com section pages. For example, the section ID for [World - Europe](https://www.reuters.com/world/europe/) stories at `www.reuters.com/world/europe/` would be `/world/europe/`. (The leading and trailing slashes are required!)
> >
> You should get a collection alias from the dotcom team. > You should get the collection alias from the dotcom team.
```svelte ```svelte
<script> <script>
import { ReferralBlock } from '@reuters-graphics/graphics-components'; import { ReferralBlock } from '@reuters-graphics/graphics-components';
</script> </script>
<ReferralBlock section="/lifestyle/sports/" /> <ReferralBlock
section="/lifestyle/sports/"
class="fmy-0"
heading="More World Cup coverage"
/>
``` ```
<Canvas of={ReferralBlockStories.Demo} /> <Canvas of={ReferralBlockStories.Demo} />
## Collection ## Collections
TK - Check if this is still relevant.
```svelte ```svelte
<script> <script>

View file

@ -34,13 +34,12 @@
name="Demo" name="Demo"
args={{ args={{
section: '/lifestyle/sports/', section: '/lifestyle/sports/',
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"
exportName="ByCollection" exportName="ByCollection"
args={{ args={{
@ -49,4 +48,4 @@
class: 'fmy-8', class: 'fmy-8',
heading: 'The latest Trump coverage', heading: 'The latest Trump coverage',
}} }}
/> /> -->

View file

@ -1,65 +1,70 @@
<!-- @migration-task Error while migrating Svelte code: Cannot set properties of undefined (setting 'next') -->
<!-- @component `ReferralBlock` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-page-furniture-referralblock--docs) --> <!-- @component `ReferralBlock` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-page-furniture-referralblock--docs) -->
<script lang="ts"> <script lang="ts">
/** ✏️ DOCUMENT your chart's props using TypeScript and JSDoc comments like below! */ // Utils
/**
* Section ID, which is often the URL path to the section page on reuters.com.
*
* Note that not all section pages will be available in the recent stories by section API.
*/
export let section: string | undefined = '/world/';
/**
* Collection alias, as defined in Arc Collections editor.
*/
export let collection: string | undefined;
/**
* Number of referrals to show.
* @required
*/
export let number: number = 4;
/**
* Link [target](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target), e.g., `_blank` or `_parent`.
*/
export let linkTarget: string = '_self';
/**
* Add a heading to the referral block.
*/
export let heading: string = '';
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
/**
* Width of the component within the text well.
* @required
*/
export let width: ContainerWidth = 'wide';
/** Add an ID to target with SCSS. */
export let id: string = '';
/** Add a class to target with SCSS. */
let cls: string = 'fmy-8';
export { cls as class };
import Block from '../Block/Block.svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { getTime } from '../SiteHeader/NavBar/NavDropdown/StoryCard/time'; import { getTime } from '../SiteHeader/NavBar/NavDropdown/StoryCard/time';
import type { Referrals } from './types';
import { articleIsNotCurrentPage } from './filterCurrentPage'; import { articleIsNotCurrentPage } from './filterCurrentPage';
import type { Article } from './types';
let clientWidth: number; // Components
import Block from '../Block/Block.svelte';
// Types
import type { Article } from './types';
import type { Referrals } from './types';
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
interface Props {
/**
* Section ID, which is often the URL path to the section page on reuters.com.
*
* Note that not all section pages will be available in the recent stories by section API.
*/
section?: string;
/**
* Collection alias, as defined in Arc Collections editor.
*/
collection?: string;
/**
* Number of referrals to show.
*/
number?: number;
/**
* Link [target](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target), e.g., `_blank` or `_parent`.
*/
linkTarget: string;
/**
* Add a heading to the referral block.
*/
heading: string;
/**
* Width of the component within the text well: 'normal' | 'wide' | 'wider' | 'widest' | 'fluid'
*/
width?: ContainerWidth;
/** Add an ID to target with SCSS. */
id?: string;
/** Add a class to target with SCSS. */
class?: string;
}
let {
section = '/world/',
collection,
number = 4,
linkTarget = '_self',
heading = '',
width = 'wide',
id = '',
class: cls = 'fmy-8',
}: Props = $props();
let clientWidth = $state(0);
const SECTION_API = 'recent-stories-by-sections-v1'; const SECTION_API = 'recent-stories-by-sections-v1';
/** @TODO - Check if collections alias API still exists*/
const COLLECTION_API = 'articles-by-collection-alias-or-id-v1'; const COLLECTION_API = 'articles-by-collection-alias-or-id-v1';
let referrals: Article[] = []; let referrals: Article[] = $state([]);
const getReferrals = async () => { const getReferrals = async () => {
const isCollection = Boolean(collection); const isCollection = Boolean(collection);
@ -76,13 +81,16 @@
}), }),
}) })
); );
const data = (await response.json()) as Referrals; const data = (await response.json()) as Referrals;
const articles = data.result.articles const articles = data.result.articles
.filter((a) => a?.headline_category || a?.kicker?.name) .filter((a) => a?.headline_category || a?.kicker?.name)
.filter((a) => a?.thumbnail?.renditions?.landscape?.['240w']) .filter((a) => a?.thumbnail?.url)
.filter((a) => !a?.content?.third_party) .filter((a) => !a?.content?.third_party)
.filter(articleIsNotCurrentPage) .filter(articleIsNotCurrentPage)
.slice(0, number); .slice(0, number);
referrals = articles; referrals = articles;
} catch { } catch {
console.warn('Unable to fetch referral links.'); console.warn('Unable to fetch referral links.');
@ -96,33 +104,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 +153,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.url}
alt="{referral.thumbnail.caption || alt={referral.thumbnail.alt_text ||
referral.thumbnail.alt_text}" referral.thumbnail.caption}
/> />
</div> </div>
</div> </div>
@ -165,7 +173,7 @@
{/if} {/if}
<style lang="scss"> <style lang="scss">
@use '../../scss/mixins' as *; @use '../../scss/mixins' as mixins;
div.block-container.stacked { div.block-container.stacked {
display: flex; display: flex;
@ -198,7 +206,7 @@
display: block; display: block;
width: calc(50% - 30px); width: calc(50% - 30px);
max-width: 450px; max-width: 450px;
@include fmy-1; @include mixins.fmy-1;
&:hover { &:hover {
.title { .title {
@ -212,25 +220,25 @@
.headline { .headline {
display: inline-block; display: inline-block;
width: calc(100% - 9rem); width: calc(100% - 9rem);
@include fpr-2; @include mixins.fpr-2;
.kicker { .kicker {
@include text-xxs; @include mixins.text-xxs;
font-family: Knowledge, sans-serif; font-family: Knowledge, sans-serif;
} }
.title { .title {
@include font-medium; @include mixins.font-medium;
@include text-sm; @include mixins.text-sm;
@include text-primary; @include mixins.text-primary;
font-family: Knowledge, sans-serif; font-family: Knowledge, sans-serif;
} }
.publish-time { .publish-time {
@include text-xxs; @include mixins.text-xxs;
font-family: Knowledge, sans-serif; font-family: Knowledge, sans-serif;
} }
} }
.image-container { .image-container {
border-radius: 0.25rem; border-radius: 0.25rem;
border: 1px solid $theme-colour-brand-rules; border: 1px solid mixins.$theme-colour-brand-rules;
width: 9rem; width: 9rem;
&.xs { &.xs {
width: 7rem; width: 7rem;