@reuters-graphics/graphics-components 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,7 +21,7 @@ export interface ScrollerStep {
21
21
  /**
22
22
  * A background component
23
23
  */
24
- background: Component;
24
+ background: Component | undefined;
25
25
  /**
26
26
  * Optional props for background component
27
27
  */
@@ -1,4 +1,4 @@
1
- export type LeaderboardAd = {
1
+ export type LeaderboardAdType = {
2
2
  mobile: {
3
3
  adType: 'leaderboard';
4
4
  placementName: 'reuters_mobile_leaderboard';
@@ -8,7 +8,7 @@ export type LeaderboardAd = {
8
8
  placementName: 'reuters_desktop_leaderboard_atf';
9
9
  };
10
10
  };
11
- export type SponsorshipAd = {
11
+ export type SponsorshipAdType = {
12
12
  mobile: {
13
13
  adType: 'sponsorlogo';
14
14
  placementName: 'reuters_sponsorlogo';
@@ -18,7 +18,7 @@ export type SponsorshipAd = {
18
18
  placementName: 'reuters_sponsorlogo';
19
19
  };
20
20
  };
21
- export type InlineAd = {
21
+ export type InlineAdType = {
22
22
  mobile: {
23
23
  adType: 'mpu' | 'native' | 'mpu2';
24
24
  placementName: 'reuters_mobile_mpu_1' | 'reuters_mobile_mpu_2' | 'reuters_mobile_mpu_3';
@@ -28,7 +28,7 @@ export type InlineAd = {
28
28
  placementName: 'reuters_desktop_native_1' | 'reuters_desktop_native_2' | 'reuters_desktop_native_3';
29
29
  };
30
30
  };
31
- export type DesktopPlacementName = LeaderboardAd['desktop']['placementName'] | SponsorshipAd['desktop']['placementName'] | InlineAd['desktop']['placementName'];
32
- export type MobilePlacementName = LeaderboardAd['mobile']['placementName'] | SponsorshipAd['mobile']['placementName'] | InlineAd['mobile']['placementName'];
33
- export type DesktopAdType = LeaderboardAd['desktop']['adType'] | SponsorshipAd['desktop']['adType'] | InlineAd['desktop']['adType'];
34
- export type MobileAdType = LeaderboardAd['mobile']['adType'] | SponsorshipAd['mobile']['adType'] | InlineAd['mobile']['adType'];
31
+ export type DesktopPlacementName = LeaderboardAdType['desktop']['placementName'] | SponsorshipAdType['desktop']['placementName'] | InlineAdType['desktop']['placementName'];
32
+ export type MobilePlacementName = LeaderboardAdType['mobile']['placementName'] | SponsorshipAdType['mobile']['placementName'] | InlineAdType['mobile']['placementName'];
33
+ export type DesktopAdType = LeaderboardAdType['desktop']['adType'] | SponsorshipAdType['desktop']['adType'] | InlineAdType['desktop']['adType'];
34
+ export type MobileAdType = LeaderboardAdType['mobile']['adType'] | SponsorshipAdType['mobile']['adType'] | InlineAdType['mobile']['adType'];
@@ -2,7 +2,7 @@
2
2
  <!-- @component `InlineAd` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-ads-analytics-inlinead--docs) -->
3
3
  <script lang="ts">
4
4
  import Block from '../Block/Block.svelte';
5
- import type { InlineAd } from './@types/ads';
5
+ import type { InlineAdType } from './@types/ads';
6
6
  import ResponsiveAd from './ResponsiveAd.svelte';
7
7
 
8
8
  interface Props {
@@ -16,7 +16,7 @@
16
16
 
17
17
  let { id = '', class: cls = 'my-12', n = 1 }: Props = $props();
18
18
 
19
- const desktopPlacementName: InlineAd['desktop']['placementName'] = `reuters_desktop_native_${n}`;
19
+ const desktopPlacementName: InlineAdType['desktop']['placementName'] = `reuters_desktop_native_${n}`;
20
20
  </script>
21
21
 
22
22
  <Block {id} class="freestar-adslot {cls}">
@@ -1,4 +1,3 @@
1
- import type { InlineAd } from './@types/ads';
2
1
  interface Props {
3
2
  /** Add an ID to target with SCSS. */
4
3
  id?: string;
@@ -1,6 +1,6 @@
1
1
  <!-- @component `LeaderboardAd` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-ads-analytics-leaderboardad--docs) -->
2
2
  <script lang="ts">
3
- import type { LeaderboardAd } from './@types/ads';
3
+ import type { LeaderboardAdType } from './@types/ads';
4
4
  import ResponsiveAd from './ResponsiveAd.svelte';
5
5
  import { onMount } from 'svelte';
6
6
 
@@ -16,7 +16,7 @@
16
16
  let windowWidth = $state(1200);
17
17
  let adSize = $derived(windowWidth < 1024 ? 110 : 275);
18
18
 
19
- const desktopPlacementName: LeaderboardAd['desktop']['placementName'] =
19
+ const desktopPlacementName: LeaderboardAdType['desktop']['placementName'] =
20
20
  'reuters_desktop_leaderboard_atf';
21
21
 
22
22
  let sticky = $state(false);
@@ -1,4 +1,3 @@
1
- import type { LeaderboardAd } from './@types/ads';
2
1
  interface Props {
3
2
  /** Add an ID to target with SCSS. */
4
3
  id?: string;
@@ -2,7 +2,7 @@
2
2
  <!-- @component `SponsorshipAd` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-ads-analytics-sponsorshipad--docs) -->
3
3
  <script lang="ts">
4
4
  import Block from '../Block/Block.svelte';
5
- import type { SponsorshipAd } from './@types/ads';
5
+ import type { SponsorshipAdType } from './@types/ads';
6
6
  import ResponsiveAd from './ResponsiveAd.svelte';
7
7
 
8
8
  interface Props {
@@ -18,7 +18,7 @@
18
18
 
19
19
  let { id = '', class: cls = 'my-12', adLabel = '' }: Props = $props();
20
20
 
21
- const desktopPlacementName: SponsorshipAd['desktop']['placementName'] =
21
+ const desktopPlacementName: SponsorshipAdType['desktop']['placementName'] =
22
22
  'reuters_sponsorlogo';
23
23
  </script>
24
24
 
@@ -1,4 +1,3 @@
1
- import type { SponsorshipAd } from './@types/ads';
2
1
  interface Props {
3
2
  /** Add an ID to target with SCSS. */
4
3
  id?: string;
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ data: {
4
+ index: number;
5
+ embed: string;
6
+ title: string;
7
+ }[];
8
+ selected: string;
9
+ }
10
+
11
+ let { data = [], selected = $bindable() }: Props = $props();
12
+ </script>
13
+
14
+ <form>
15
+ <label for="embed-options">Select an embed</label>
16
+ <select id="embed-options" bind:value={selected}>
17
+ {#each data as d (d.index)}
18
+ <option value={d.embed}>{d.title}</option>
19
+ {/each}
20
+ </select>
21
+ </form>
22
+
23
+ <style>/* Generated from
24
+ https://utopia.fyi/space/calculator/?c=320,18,1.125,1280,21,1.25,7,3,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12
25
+ */
26
+ /* Generated from
27
+ https://utopia.fyi/space/calculator/?c=320,18,1.125,1280,21,1.25,7,3,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12
28
+ */
29
+ /* Scales by 1.125 */
30
+ label {
31
+ margin-bottom: 0.25rem;
32
+ display: inline-flex;
33
+ font-size: 0.75rem;
34
+ color: #aaa;
35
+ font-family: var(--theme-font-family-sans-serif);
36
+ }
37
+
38
+ select {
39
+ width: 100%;
40
+ padding: 0.5rem 0.75rem;
41
+ background: none;
42
+ font-size: 1rem;
43
+ border: 0;
44
+ border-radius: 0 !important;
45
+ background-color: #fff;
46
+ border: 1px solid #ddd;
47
+ font-family: var(--theme-font-family-sans-serif);
48
+ }
49
+
50
+ select:focus {
51
+ outline: none;
52
+ border: 1px solid #ccc;
53
+ }</style>
@@ -0,0 +1,11 @@
1
+ interface Props {
2
+ data: {
3
+ index: number;
4
+ embed: string;
5
+ title: string;
6
+ }[];
7
+ selected: string;
8
+ }
9
+ declare const Index: import("svelte").Component<Props, {}, "selected">;
10
+ type Index = ReturnType<typeof Index>;
11
+ export default Index;
@@ -7,6 +7,7 @@
7
7
  import { width } from './stores';
8
8
  import getUniqNames from './uniqNames';
9
9
  import Typeahead from './Typeahead/index.svelte';
10
+ import Dropdown from './Dropdown/index.svelte';
10
11
  import ReutersGraphicsLogo from '../ReutersGraphicsLogo/ReutersGraphicsLogo.svelte';
11
12
 
12
13
  interface Props {
@@ -14,6 +15,7 @@
14
15
  breakpoints?: number[];
15
16
  minFrameWidth?: number;
16
17
  maxFrameWidth?: number;
18
+ searchType?: 'dropdown' | 'typeahead';
17
19
  }
18
20
 
19
21
  let {
@@ -21,6 +23,7 @@
21
23
  breakpoints = [330, 510, 660, 930, 1200],
22
24
  minFrameWidth = 320,
23
25
  maxFrameWidth = 1200,
26
+ searchType = 'dropdown',
24
27
  }: Props = $props();
25
28
 
26
29
  const getDefaultEmbed = (embeds: Props['embeds']) => {
@@ -71,37 +74,62 @@
71
74
  <p>No embeds to show.</p>
72
75
  </div>
73
76
  {:else}
74
- <div id="typeahead-container">
75
- <div class="embed-link">
76
- <a
77
- rel="external"
78
- target="_blank"
79
- href={activeEmbed}
80
- title={activeEmbed}
81
- >
82
- Live link <Fa icon={faLink} />
83
- </a>
77
+ {#if searchType === 'typeahead'}
78
+ <div id="typeahead-container">
79
+ <div class="embed-link">
80
+ <a
81
+ rel="external"
82
+ target="_blank"
83
+ href={activeEmbed}
84
+ title={activeEmbed}
85
+ >
86
+ Live link <Fa icon={faLink} />
87
+ </a>
88
+ </div>
89
+ <Typeahead
90
+ label="Select an embed"
91
+ value={embedTitles[embeds.indexOf(activeEmbed)] ||
92
+ embedTitles[activeEmbedIndex] ||
93
+ embedTitles[0]}
94
+ extract={(d) => embedTitles[d.index]}
95
+ data={embeds.map((embed, index) => ({ index, embed }))}
96
+ showDropdownOnFocus={true}
97
+ onselect={(detail) => {
98
+ if (typeof window !== 'undefined') {
99
+ window.localStorage.setItem(
100
+ 'framer-active-embed',
101
+ detail.original.embed
102
+ );
103
+ }
104
+ activeEmbed = detail.original.embed;
105
+ // activeEmbedIndex = detail.original.index;
106
+ }}
107
+ />
84
108
  </div>
85
- <Typeahead
86
- label="Select an embed"
87
- value={embedTitles[embeds.indexOf(activeEmbed)] ||
88
- embedTitles[activeEmbedIndex] ||
89
- embedTitles[0]}
90
- extract={(d) => embedTitles[d.index]}
91
- data={embeds.map((embed, index) => ({ index, embed }))}
92
- showDropdownOnFocus={true}
93
- onselect={(detail) => {
94
- if (typeof window !== 'undefined') {
95
- window.localStorage.setItem(
96
- 'framer-active-embed',
97
- detail.original.embed
98
- );
99
- }
100
- activeEmbed = detail.original.embed;
101
- // activeEmbedIndex = detail.original.index;
102
- }}
103
- />
104
- </div>
109
+ {:else}
110
+ <div id="dropdown-container">
111
+ <div>
112
+ <div class="embed-link">
113
+ <a
114
+ rel="external"
115
+ target="_blank"
116
+ href={activeEmbed}
117
+ title={activeEmbed}
118
+ >
119
+ Live link <Fa icon={faLink} />
120
+ </a>
121
+ </div>
122
+ </div>
123
+ <Dropdown
124
+ data={embeds.map((embed, index) => ({
125
+ index,
126
+ embed,
127
+ title: embedTitles[index],
128
+ }))}
129
+ bind:selected={activeEmbed}
130
+ />
131
+ </div>
132
+ {/if}
105
133
 
106
134
  <div id="preview-label" style="width:{$width}px;">
107
135
  <p>Preview</p>
@@ -143,28 +171,29 @@ header {
143
171
  font-family: var(--theme-font-family-note);
144
172
  }
145
173
 
146
- div#typeahead-container {
174
+ div#typeahead-container,
175
+ div#dropdown-container {
147
176
  max-width: 660px;
148
177
  margin: 0 auto 15px;
149
178
  position: relative;
150
179
  }
151
-
152
- div#typeahead-container div.embed-link {
180
+ div#typeahead-container div.embed-link,
181
+ div#dropdown-container div.embed-link {
153
182
  position: absolute;
154
183
  top: 0;
155
184
  right: 0;
156
185
  display: inline-block;
157
186
  z-index: 2;
158
187
  }
159
-
160
- div#typeahead-container div.embed-link a {
188
+ div#typeahead-container div.embed-link a,
189
+ div#dropdown-container div.embed-link a {
161
190
  font-family: "Knowledge", "Source Sans Pro", Arial, sans-serif;
162
191
  color: #bbb;
163
192
  font-size: 12px;
164
193
  text-decoration: none !important;
165
194
  }
166
-
167
- div#typeahead-container div.embed-link a:hover {
195
+ div#typeahead-container div.embed-link a:hover,
196
+ div#dropdown-container div.embed-link a:hover {
168
197
  color: #666;
169
198
  }
170
199
 
@@ -3,6 +3,7 @@ interface Props {
3
3
  breakpoints?: number[];
4
4
  minFrameWidth?: number;
5
5
  maxFrameWidth?: number;
6
+ searchType?: 'dropdown' | 'typeahead';
6
7
  }
7
8
  declare const Framer: import("svelte").Component<Props, {}, "">;
8
9
  type Framer = ReturnType<typeof Framer>;
@@ -27,8 +27,7 @@
27
27
  if ($width > maxWidth) width.set(maxWidth);
28
28
  });
29
29
 
30
- // svelte-ignore state_referenced_locally
31
- let offset = $state(($width - minWidth) / pixelRange);
30
+ let offset = $derived(($width - minWidth) / pixelRange);
32
31
 
33
32
  let sliding = $state(false);
34
33
  let isFocused = $state(false);
@@ -55,7 +54,7 @@
55
54
  } else if (keyCode === 37) {
56
55
  offset = Math.max(0, offset - pixelWidth / sliderWidth);
57
56
  }
58
- width.set(getPx());
57
+ $width = getPx();
59
58
  };
60
59
  const start = (e: MouseEvent) => {
61
60
  sliding = true;
@@ -77,17 +76,17 @@
77
76
  .filter((b) => b <= maxWidth)
78
77
  .filter((b) => b > $width);
79
78
  if (availableBreakpoints.length === 0) {
80
- width.set(maxWidth);
79
+ $width = maxWidth;
81
80
  } else {
82
- width.set(availableBreakpoints[0]);
81
+ $width = availableBreakpoints[0];
83
82
  }
84
83
  };
85
84
  const decrement = () => {
86
85
  const availableBreakpoints = breakpoints.filter((b) => b < $width);
87
86
  if (availableBreakpoints.length === 0) {
88
- width.set(minWidth);
87
+ $width = minWidth;
89
88
  } else {
90
- width.set(availableBreakpoints.slice(-1)[0]);
89
+ $width = availableBreakpoints.slice(-1)[0];
91
90
  }
92
91
  };
93
92
  </script>
@@ -177,7 +177,6 @@
177
177
 
178
178
  <svelte:window
179
179
  onclick={({ target }) => {
180
- console.log('HELLO', !comboboxRef?.contains(target as Node));
181
180
  if (!hideDropdown && !comboboxRef?.contains(target as Node)) {
182
181
  close();
183
182
  }
@@ -67,6 +67,9 @@
67
67
  let referrals: Article[] = $state([]);
68
68
 
69
69
  const getReferrals = async () => {
70
+ if (typeof window === 'undefined') return;
71
+ // fetch only reliably works on prod sites
72
+ if (window?.location?.hostname !== 'www.reuters.com') return;
70
73
  const isCollection = Boolean(collection);
71
74
  const API = isCollection ? COLLECTION_API : SECTION_API;
72
75
  try {
@@ -185,9 +185,11 @@
185
185
  <meta property="fb:admins" content="625796953" />
186
186
  <meta property="fb:admins" content="571759798" />
187
187
 
188
+ <!-- svelte-ignore hydration_html_changed -->
188
189
  {@html `<${'script'} type="application/ld+json">${JSON.stringify(
189
190
  orgLdJson
190
191
  )}</script>`}
192
+ <!-- svelte-ignore hydration_html_changed -->
191
193
  {@html `<${'script'} type="application/ld+json">${JSON.stringify(
192
194
  articleLdJson
193
195
  )}</script>`}
@@ -25,6 +25,11 @@
25
25
  }
26
26
 
27
27
  let { links = {} }: Props = $props();
28
+
29
+ const normaliseSocialName = (name: string) => {
30
+ if (name === 'twitter') return 'X';
31
+ return name;
32
+ };
28
33
  </script>
29
34
 
30
35
  {#if links.social_links}
@@ -42,7 +47,10 @@
42
47
  {@const SvelteComponent =
43
48
  symbols[link.type as keyof typeof symbols]}
44
49
  <li class="social-links symbol">
45
- <a href={normalizeUrl(link.url)}>
50
+ <a
51
+ href={normalizeUrl(link.url)}
52
+ aria-label="Visit Reuters on {normaliseSocialName(link.type)}"
53
+ >
46
54
  <div class="button">
47
55
  <div class="social">
48
56
  <SvelteComponent />
@@ -37,7 +37,11 @@
37
37
  textColour="var(--nav-primary)"
38
38
  />
39
39
  </div>
40
- <button class="button close-button" onclick={releaseMobileMenu}>
40
+ <button
41
+ class="button close-button"
42
+ aria-label="Close menu"
43
+ onclick={releaseMobileMenu}
44
+ >
41
45
  <div class="button-container">
42
46
  <CloseIcon />
43
47
  </div>
@@ -69,7 +69,7 @@
69
69
  };
70
70
  </script>
71
71
 
72
- <div class="dropdown">
72
+ <div class="dropdown" data-chromatic="ignore">
73
73
  <div class="dropdown-container">
74
74
  <div class="inner">
75
75
  <div class="submenu">
@@ -78,7 +78,7 @@
78
78
  </div>
79
79
  </div>
80
80
  <div class="stories-container">
81
- <div class="inner" data-chromatic="ignore">
81
+ <div class="inner">
82
82
  {#if stories.length > 0}
83
83
  <span class="latest">{headingText}</span>
84
84
  <ul class="story-list">
@@ -66,7 +66,7 @@
66
66
  <a href={normalizeUrl(section.url)}>
67
67
  {section.name}
68
68
  </a>
69
- <button class="button">
69
+ <button class="button" aria-label="{section.name} menu">
70
70
  <DownArrow rotate={section.id === $activeSection} />
71
71
  </button>
72
72
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reuters-graphics/graphics-components",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "homepage": "https://reuters-graphics.github.io/graphics-components",
@@ -1,11 +0,0 @@
1
- An embed tool for development in the graphics kit.
2
-
3
- ```svelte
4
- <script>
5
- import { Framer } from '@reuters-graphics/graphics-components';
6
-
7
- const embeds = ['/embeds/my-chart/index.html'];
8
- </script>
9
-
10
- <Framer embeds="{embeds}" />
11
- ```