Merge remote-tracking branch 'origin/main' into scrolly-video

This commit is contained in:
Sudev Kiyada 2025-08-07 19:40:00 +05:30
commit 9598b089eb
Failed to extract signature
21 changed files with 128 additions and 104 deletions

View file

@ -1,5 +0,0 @@
---
'@reuters-graphics/graphics-components': patch
---
Adds new Headpile component.

View file

@ -1,5 +1,47 @@
# @reuters-graphics/graphics-components
## 3.0.12
### Patch Changes
- 771ccb4: Fixes sizing issue for Framer
## 3.0.11
### Patch Changes
- 31caab2: Fix typos in Scroller
## 3.0.10
### Patch Changes
- cf7e513: Updated oneTrustId to production ID
## 3.0.9
### Patch Changes
- 18e49eb: renames Theme and CustomTheme types
## 3.0.8
### Patch Changes
- bdf3918: Updates Visible to allow unit specification for top, bototm, right, left and adds a demo
## 3.0.7
### Patch Changes
- f80e450: Removes Parsely page analytics
## 3.0.6
### Patch Changes
- a205a35: Adds new Headpile component.
## 3.0.5
### Patch Changes

View file

@ -1,6 +1,6 @@
{
"name": "@reuters-graphics/graphics-components",
"version": "3.0.5",
"version": "3.0.12",
"type": "module",
"private": false,
"homepage": "https://reuters-graphics.github.io/graphics-components",

View file

@ -4,7 +4,7 @@ import Ias from './ias';
const ONETRUST_LOGS = 'ot_logs';
const ONETRUST_GEOLOCATION_MOCK = 'ot_geolocation_mock';
const ONETRUST_SCRIPT_ID = '38cb75bd-fbe1-4ac8-b4af-e531ab368caf-test';
const ONETRUST_SCRIPT_ID = '38cb75bd-fbe1-4ac8-b4af-e531ab368caf';
export const loadBootstrap = () => {
(<any>window).freestar = (<any>window).freestar || {};

View file

@ -3,13 +3,11 @@
<script module>
import { registerPageview as registerChartbeatPageview } from './providers/chartbeat';
import { registerPageview as registerGAPageview } from './providers/ga';
import { registerPageview as registerParselyPageview } from './providers/parsely';
/** Register virtual pageviews when using client-side routing in multipage applications. */
function registerPageview() {
registerChartbeatPageview();
registerGAPageview();
registerParselyPageview();
}
export { registerPageview };
@ -21,7 +19,7 @@
}
import { onMount } from 'svelte';
import { ga, chartbeat, parsely } from './providers';
import { ga, chartbeat } from './providers';
interface Props {
/**
* Used to associate a page with its author(s) in Chartbeat.
@ -34,6 +32,5 @@
onMount(() => {
ga();
chartbeat(authors);
parsely();
});
</script>

View file

@ -1,3 +1,2 @@
export { default as ga } from './ga';
export { default as chartbeat } from './chartbeat';
export { default as parsely } from './parsely';

View file

@ -1,32 +0,0 @@
const SITE_ID = 'reuters.com';
const attachScript = () => {
const b = document.body;
const e = document.createElement('script');
e.id = 'parsely-cfg';
e.src = `//cdn.parsely.com/keys/${SITE_ID}/p.js`;
e.setAttribute('async', '');
e.setAttribute('defer', '');
b.appendChild(e);
};
export default () => {
window.PARSELY = window.PARSELY || {
autotrack: false,
onReady() {
window.PARSELY.updateDefaults({
data: {
is_logged_in: false,
},
});
window.PARSELY.beacon.trackPageView();
},
};
attachScript();
};
export const registerPageview = () => {
if (typeof window === 'undefined' || !window.PARSELY) return;
window.PARSELY.beacon.trackPageView();
};

View file

@ -201,6 +201,7 @@
}
#frame-parent {
box-sizing: content-box;
border: 1px solid #ddd;
margin: 0 auto;
width: var(--width);

View file

@ -25,7 +25,7 @@
{#each steps as step, i}
{#if showStep(i)}
<div
class={`step step-${i + 1} w-full absolute`}
class={`step-background step-${i + 1} w-full absolute`}
class:visible={isVisible(i)}
class:invisible={!isVisible(i)}
>

View file

@ -122,7 +122,7 @@ Then parse the relevant ArchieML block object before passing to the `Scroller` c
{#if block.type === 'ai-scroller'}
<Scroller
id={block.id}
backgroundWidth={block.width}
backgroundWidth={block.backgroundWidth}
foregroundPosition={block.foregroundPosition}
stackBackground={truthy(block.stackBackground)}
steps={block.steps.map((step) => ({

View file

@ -42,12 +42,12 @@ export interface CustomFont {
size?: Partial<FontSize>;
}
export interface Theme {
export interface ThemeConfig {
colour: Colour;
font: Font;
}
export interface CustomTheme {
export interface CustomThemeConfig {
colour?: Partial<Colour>;
font?: Partial<CustomFont>;
[customProperty: string]: unknown;

View file

@ -14,7 +14,7 @@
import mergeThemes from './utils/merge.js';
// Types
import type { CustomTheme, Theme } from './@types/component';
import type { CustomThemeConfig, ThemeConfig } from './@types/component';
import type { Snippet } from 'svelte';
type Base = 'light' | 'dark';
@ -22,7 +22,7 @@
/** Custom theme object. Can be a partial theme with just
* what you want to change.
*/
theme?: CustomTheme | Theme;
theme?: CustomThemeConfig | ThemeConfig;
/**
* Base theme is one of `light` or `dark` and will be merged
* with your custom theme to fill in any values you don't

View file

@ -1,4 +1,4 @@
/** @type {Omit<import('../@types/component').Theme, "colour">} */
/** @type {Omit<import('../@types/component').ThemeConfig, "colour">} */
/* Generated from
https://www.fluid-type-scale.com/calculate?minFontSize=18&minWidth=320&minRatio=1.125&maxFontSize=21&maxWidth=1280&maxRatio=1.25&steps=xxs%2Cxs%2Csm%2Cbase%2Clg%2Cxl%2C2xl%2C3xl%2C4xl%2C5xl%2C6xl&baseStep=base&prefix=&decimals=2&useRems=on&remValue=16&previewFont=Noto+Sans&previewText=Almost+before+we+knew+it%2C+we+had+left+the+ground&previewWidth=0
*/

View file

@ -1,6 +1,6 @@
import common from './common.js';
/** @type {import('../@types/component').Theme} */
/** @type {import('../@types/component').ThemeConfig} */
export default {
...common,
colour: {

View file

@ -1,6 +1,6 @@
import common from './common.js';
/** @type {import('../@types/component').Theme} */
/** @type {import('../@types/component').ThemeConfig} */
export default {
...common,
colour: {

View file

@ -1,4 +1,4 @@
import type { Theme, CustomTheme } from '../@types/component';
import type { ThemeConfig, CustomThemeConfig } from '../@types/component';
function isObject(item: unknown): item is Record<string, unknown> {
return item !== null && typeof item === 'object' && !Array.isArray(item);
@ -9,7 +9,7 @@ function isObject(item: unknown): item is Record<string, unknown> {
*/
export default function merge<T extends Record<string, unknown>>(
target: T,
...sources: (Theme | CustomTheme)[]
...sources: (ThemeConfig | CustomThemeConfig)[]
): T {
if (!sources.length) return target;
const source = sources.shift();

View file

@ -19,7 +19,8 @@ By default, `visible` will switch between `false` and `true` whenever the elemen
import { Visible } from '@reuters-graphics/graphics-components';
</script>
<Visible>
<!-- Optionally set your own `top`, `bottom`, `right` and `left` values with `px` or `%` units -->
<Visible top="10px">
{#snippet children(visible)}
{#if visible}
<p>Visible!</p>

View file

@ -2,6 +2,7 @@
import { defineMeta } from '@storybook/addon-svelte-csf';
import Visible from './Visible.svelte';
import VisibleDemo from './demo/VisibleDemo.svelte';
const { Story } = defineMeta({
title: 'Components/Utilities/Visible',
@ -9,14 +10,6 @@
});
</script>
<Story name="Demo" tags={['!autodocs', '!dev']}>
<Visible>
{#snippet children(visible)}
{#if visible}
<p>Visible!</p>
{:else}
<p>Not yet visible.</p>
{/if}
{/snippet}
</Visible>
<Story name="Demo">
<VisibleDemo />
</Story>

View file

@ -9,14 +9,14 @@
* Useful for loading expensive images or other media and then keeping them around once they're first loaded.
*/
once?: boolean;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top`. */
top?: number;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `bottom`. */
bottom?: number;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `left`. */
left?: number;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `right`. */
right?: number;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `top` with units. Units must be `px` or other [absolute lengths units](https://arc.net/l/quote/jkukcxqq), or `%`. */
top?: string;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `bottom` with units. Units must be `px` or other [absolute lengths units](https://arc.net/l/quote/jkukcxqq), or `%`. */
bottom?: string;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `left` with units. Units must be `px` or other [absolute lengths units](https://arc.net/l/quote/jkukcxqq), or `%`. */
left?: string;
/** Set Intersection Observer [rootMargin](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#rootmargin) `right` with units. Units must be `px` or other [absolute lengths units](https://arc.net/l/quote/jkukcxqq), or `%`. */
right?: string;
/** Set the Intersection Observer [threshold](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#threshold). */
threshold?: number;
children?: Snippet<[boolean]>;
@ -24,10 +24,10 @@
let {
once = false,
top = 0,
bottom = 0,
left = 0,
right = 0,
top = '0px',
bottom = '0px',
left = '0px',
right = '0px',
threshold = 0,
children,
}: Props = $props();
@ -37,7 +37,7 @@
onMount(() => {
if (typeof IntersectionObserver !== 'undefined') {
const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`;
const rootMargin = `${bottom} ${left} ${top} ${right}`;
const observer = new IntersectionObserver(
(entries) => {
@ -53,28 +53,18 @@
);
if (container) observer.observe(container);
return () => {
if (container) observer.observe(container);
if (container) observer.unobserve(container);
};
}
function handler() {
if (container) {
const bcr = container.getBoundingClientRect();
visible =
bcr.bottom + bottom > 0 &&
bcr.right + right > 0 &&
bcr.top - top < window.innerHeight &&
bcr.left - left < window.innerWidth;
}
if (visible && once) {
window.removeEventListener('scroll', handler);
}
}
window.addEventListener('scroll', handler);
return () => window.removeEventListener('scroll', handler);
});
</script>
<div bind:this={container}>
<div
bind:this={container}
class="visibility-tracker"
class:visible
class:not-visible={!visible}
>
{#if children}
{@render children(visible)}
{/if}

View file

@ -0,0 +1,46 @@
<script lang="ts">
import Visible from '../Visible.svelte';
import BodyText from '../../BodyText/BodyText.svelte';
import Block from '../../Block/Block.svelte';
import FeaturePhoto from '../../FeaturePhoto/FeaturePhoto.svelte';
import sharkSrc from '../../FeaturePhoto/images/shark.jpg';
let top = '150px';
const demoText =
'Take a look at the *Elements* tab in Inspector to see how the photo in the middle of the page appears in the DOM only when its container comes into view.';
let demoText2 = $derived(
`The top value for \`rootMargin\` is set to \`${top}px\` in this demo. Read about how \`rootMargin\` affects the <a href='https://codepen.io/michellebarker/full/xxwLpRG'>Intersection Observer's behaviour here</a>.`
);
const text =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
</script>
<BodyText text={`**${demoText}**`} />
<BodyText text={`**${demoText2}**`} />
<BodyText {text} />
<BodyText {text} />
<BodyText {text} />
<BodyText {text} />
<Visible {top} once={false}>
{#snippet children(visible)}
{#if visible}
<FeaturePhoto
src={sharkSrc}
altText="A shark!"
caption="Carcharodon carcharias - REUTERS"
/>
{:else}
<Block><h2>Not yet visible.</h2></Block>
{/if}
{/snippet}
</Visible>
<BodyText {text} />
<BodyText {text} />
<BodyText {text} />
<BodyText {text} />
<BodyText {text} />

8
src/globals.d.ts vendored
View file

@ -21,14 +21,6 @@ declare global {
};
/** Graphics ads */
graphicsAdQueue: any[];
/** Parsely */
PARSELY: {
onLoad: () => void;
beacon: {
trackPageView: () => void;
};
updateDefaults: (params: any) => void;
};
}
}