@reuters-graphics/graphics-components 3.9.0 → 3.10.1

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.
Files changed (67) hide show
  1. package/dist/llm-docs/components/AdSlot.md +11 -0
  2. package/dist/llm-docs/components/Analytics.md +89 -0
  3. package/dist/llm-docs/components/Article.md +183 -0
  4. package/dist/llm-docs/components/BeforeAfter.md +170 -0
  5. package/dist/llm-docs/components/BioBox.md +74 -0
  6. package/dist/llm-docs/components/Block.md +211 -0
  7. package/dist/llm-docs/components/BlogPost.md +68 -0
  8. package/dist/llm-docs/components/BlogTOC.md +91 -0
  9. package/dist/llm-docs/components/BodyText.md +143 -0
  10. package/dist/llm-docs/components/Byline.md +242 -0
  11. package/dist/llm-docs/components/ClockWall.md +48 -0
  12. package/dist/llm-docs/components/DatawrapperChart.md +87 -0
  13. package/dist/llm-docs/components/DocumentCloud.md +47 -0
  14. package/dist/llm-docs/components/EmbedPreviewerLink.md +35 -0
  15. package/dist/llm-docs/components/EndNotes.md +79 -0
  16. package/dist/llm-docs/components/FeaturePhoto.md +102 -0
  17. package/dist/llm-docs/components/Framer.md +44 -0
  18. package/dist/llm-docs/components/Geocoder.md +49 -0
  19. package/dist/llm-docs/components/GraphicBlock.md +319 -0
  20. package/dist/llm-docs/components/Headline.md +248 -0
  21. package/dist/llm-docs/components/Headpile.md +55 -0
  22. package/dist/llm-docs/components/HeroHeadline.md +515 -0
  23. package/dist/llm-docs/components/HorizontalScroller.md +523 -0
  24. package/dist/llm-docs/components/InfoBox.md +196 -0
  25. package/dist/llm-docs/components/KinesisLogo.md +34 -0
  26. package/dist/llm-docs/components/LanguageButton.md +171 -0
  27. package/dist/llm-docs/components/Legend.md +251 -0
  28. package/dist/llm-docs/components/Lottie.md +464 -0
  29. package/dist/llm-docs/components/PaddingReset.md +78 -0
  30. package/dist/llm-docs/components/PhotoPack.md +237 -0
  31. package/dist/llm-docs/components/PymChild.md +49 -0
  32. package/dist/llm-docs/components/ReferralBlock.md +119 -0
  33. package/dist/llm-docs/components/ReutersGraphicsLogo.md +37 -0
  34. package/dist/llm-docs/components/ReutersLogo.md +35 -0
  35. package/dist/llm-docs/components/SEO.md +113 -0
  36. package/dist/llm-docs/components/Scroller.md +350 -0
  37. package/dist/llm-docs/components/ScrollerBase.md +104 -0
  38. package/dist/llm-docs/components/ScrollerVideo.md +576 -0
  39. package/dist/llm-docs/components/SearchInput.md +44 -0
  40. package/dist/llm-docs/components/ShareBar.md +78 -0
  41. package/dist/llm-docs/components/SimpleTimeline.md +141 -0
  42. package/dist/llm-docs/components/SiteFooter.md +77 -0
  43. package/dist/llm-docs/components/SiteHeader.md +55 -0
  44. package/dist/llm-docs/components/SiteHeadline.md +111 -0
  45. package/dist/llm-docs/components/Spinner.md +43 -0
  46. package/dist/llm-docs/components/Table.md +298 -0
  47. package/dist/llm-docs/components/Theme.md +266 -0
  48. package/dist/llm-docs/components/TileMap.md +477 -0
  49. package/dist/llm-docs/components/ToolsHeader.md +46 -0
  50. package/dist/llm-docs/components/Video.md +254 -0
  51. package/dist/llm-docs/components/Visible.md +54 -0
  52. package/dist/llm-docs/components/cssVariables.md +40 -0
  53. package/dist/llm-docs/components/index.md +59 -0
  54. package/dist/llm-docs/components/resizeObserver.md +21 -0
  55. package/dist/llm-docs/guides/archieml.md +406 -0
  56. package/dist/llm-docs/guides/colours.md +443 -0
  57. package/dist/llm-docs/guides/customising-with-scss.md +61 -0
  58. package/dist/llm-docs/guides/graphics-kit.md +25 -0
  59. package/dist/llm-docs/guides/index.md +16 -0
  60. package/dist/llm-docs/guides/intro.md +21 -0
  61. package/dist/llm-docs/guides/layout.md +13 -0
  62. package/dist/llm-docs/guides/llm-docs.md +71 -0
  63. package/dist/llm-docs/guides/styles.md +16 -0
  64. package/dist/llm-docs/guides/theming.md +100 -0
  65. package/dist/llm-docs/guides/tokens.md +150 -0
  66. package/dist/llm-docs/index.md +36 -0
  67. package/package.json +23 -3
@@ -0,0 +1,576 @@
1
+ # ScrollerVideo
2
+
3
+ **Category:** Components/Graphics/ScrollerVideo
4
+
5
+ **Import:** `import { ScrollerVideo } from '@reuters-graphics/graphics-components'`
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Default | Required | Description |
10
+ |------|------|---------|:--------:|-------------|
11
+ | `class` | `string` | `''` | | CSS class for scroller container |
12
+ | `id` | `string` | `''` | | ID of the scroller container |
13
+ | `scrollerVideo` | `ScrollerVideo` | `$bindable()` | | Bindable instance of ScrollerVideo |
14
+ | `src` | `string` | — | ✓ | Video source URL |
15
+ | `videoPercentage` | `number` | — | | Bindable percentage value to control video playback. **Ranges from 0 to 1** |
16
+ | `transitionSpeed` | `number` | — | | Sets the maximum playbackRate for this video |
17
+ | `frameThreshold` | `number` | — | | When to stop the video animation, in seconds |
18
+ | `objectFit` | `string` | — | | How the video should be resized to fit its container Options: `contain`, `cover` |
19
+ | `sticky` | `boolean` | — | | Whether the video should have position: sticky |
20
+ | `full` | `boolean` | — | | Whether the video should take up the entire viewport |
21
+ | `trackScroll` | `boolean` | — | | Whether this object should automatically respond to scroll. Set this to **false** while manually controlling `videoPercentage` prop. |
22
+ | `lockScroll` | `boolean` | — | | Whether it ignores human scroll while it runs setVideoPercentage with enabled trackScroll |
23
+ | `useWebCodecs` | `boolean` | — | | Whether the library should use the webcodecs method. For more info, visit https://scrollyvideo.js.org/ |
24
+ | `onReady` | `() => void` | `$bindable(() => {})` | | The callback when it's ready to scroll |
25
+ | `onChange` | `() => void` | `$bindable(() => {})` | | The callback for video percentage change |
26
+ | `debug` | `boolean` | — | | Whether to log debug information. Internal library logs. |
27
+ | `showDebugInfo` | `boolean` | `false` | | Shows debug information on page |
28
+ | `height` | `string` | `'200lvh'` | | Height of the video container. Set it to 100lvh when using inside `ScrollerBase` |
29
+ | `autoplay` | `boolean` | — | | Whether the video should autoplay |
30
+ | `embedded` | `boolean` | `false` | | Variable to control component rendering on embed page |
31
+ | `embeddedProps` | `{ /** When to start the playback in terms of the component's position */ threshold?: number; /** Duration of ScrollerVideo experience as a video */ duration?: number; /** Delay before the playback */ delay?: number; }` | — | | Additional properties for embedded videos |
32
+ | `children` | `Snippet` | — | | Children render function |
33
+
34
+ ## Examples
35
+
36
+ ### Demo
37
+
38
+ ```svelte
39
+ <ScrollerVideo {...args} src={videoSrc.Goldengate} />
40
+ ```
41
+
42
+ ### Object Fit
43
+
44
+ ```svelte
45
+ <Block width="normal">
46
+ <ScrollerVideo {...args} src={videoSrc.Goldengate} objectFit="contain" />
47
+ </Block>
48
+ ```
49
+
50
+ ### Responsive videos
51
+
52
+ ```svelte
53
+ {#if width < 600}
54
+ <ScrollerVideo {...args} src={videoSrc.Video_SM} />
55
+ {:else if width < 1200}
56
+ <ScrollerVideo {...args} src={videoSrc.Video_MD} />
57
+ {:else}
58
+ <ScrollerVideo {...args} src={videoSrc.Video_LG} />
59
+ {/if}
60
+ ```
61
+
62
+ ### Embed version
63
+
64
+ ```svelte
65
+ <Embedded />
66
+ ```
67
+
68
+ ### Autoplay
69
+
70
+ ```svelte
71
+ <ScrollerVideo {...args} src={videoSrc.Goldengate} autoplay={true} />
72
+ ```
73
+
74
+ ### Time-based foregrounds with ArchieML
75
+
76
+ ```svelte
77
+ <WithTextForegrounds />
78
+ ```
79
+
80
+ ### Time-based component foregrounds with ArchieML
81
+
82
+ ```svelte
83
+ <WithAi2svelteForegrounds />
84
+ ```
85
+
86
+ ### Using with ScrollerBase
87
+
88
+ ```svelte
89
+ <WithScrollerBase />
90
+ ```
91
+
92
+ ### Advanced usecases
93
+
94
+ ```svelte
95
+ <AdvancedUsecases />
96
+ ```
97
+
98
+ ## Documentation
99
+
100
+ # ScrollerVideo
101
+
102
+ The `ScrollerVideo` component creates interactive video experiences that respond to user scrolling. It is built on top of [ScrollyVideo.js](https://scrollyvideo.js.org/) and is designed to work seamlessly with Svelte.
103
+
104
+ ## Basic demo
105
+
106
+ To use the `ScrollerVideo` component, import it and provide the video source. The scroll height defaults to `200lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `200lvh` with the `height` prop.
107
+
108
+ > 💡TIP: Use `lvh` or `svh` units instead of `vh` unit for the height, as [these units](https://www.w3.org/TR/css-values-4/#large-viewport-size) are more reliable on mobile or other devices where elements such as the address bar toggle between being shown and hidden.
109
+
110
+ [Demo](?path=/story/components-graphics-scrollervideo--demo)
111
+
112
+ ```svelte
113
+ <script lang="ts">
114
+ import { ScrollerVideo } from '@reuters-graphics/graphics-components';
115
+ </script>
116
+
117
+ <!-- Optionally set `height` to adjust scroll height -->
118
+ <ScrollerVideo src="my-video.mp4" height="500lvh" />
119
+ ```
120
+
121
+ ## Optimising videos
122
+
123
+ When using the `ScrollerVideo` component, minimise the video file size and ensure that the video is encoded in a format that is widely supported across browsers. Videos encoded at higher frame rates (FPS) are bound to crash on mobile devices, so 24 FPS is recommended.
124
+
125
+ If at any point your page crashes while using this component (happens often only on phone devices), it is likely due to the video being too large or encoded at a high frame rate. You could also try separate videos for desktop and phone devices to save quality for the desktop viewing experience.
126
+
127
+ > 💡**TIP:** Set the `showDebugInfo` prop to `true` to see video encoding information
128
+
129
+ To optimise your video for the web, you can use `ffmpeg` to convert the video to a suitable format. Here is an example terminal command that converts a video to H.264 format with a resolution of 720p and a frame rate of 24 FPS:
130
+
131
+ ```bash
132
+ npx ffmpeg -y -i <input_video_src>.mp4 -c:v libx264 -movflags +faststart -crf 24 -r 24 -g 72 -vf scale=720:-1 -profile:v high -preset veryslow -pix_fmt yuv420p -color_primaries 1 -color_trc 1 -colorspace 1 -an <output_video>.mp4
133
+ ```
134
+
135
+ Adjust the `-crf` value to control the quality. A lower `-crf` value means higher quality, with 20-24 being a generally good balance. The video framerate can be altered by using `-r` flag. Set keyframe intervals using the `-g` flag. It is advisable to keep it around 3 seconds (3 \* video framerate) for a good output. See [FFmpeg documentation](https://ffmpeg.org/ffmpeg.html) and [Testing Media Capabilities](https://cconcolato.github.io/media-mime-support/mediacapabilities.html) for more.
136
+
137
+ ## Setting custom width
138
+
139
+ By default, the `ScrollerVideo` component takes up the full width of its container. To set a custom width, you can wrap the `ScrollerVideo` component in a `<Block>` with one of the acceptable `ContainerWidth` values.
140
+
141
+ Further, it also allows you to set the `objectFit` property to control how the video should be resized to fit its container. The available options are `cover` and `contain`. The default value is `cover`.
142
+
143
+ [Demo](?path=/story/components-graphics-scrollervideo--object-fit)
144
+
145
+ ```svelte
146
+ <script lang="ts">
147
+ import { Block, ScrollerVideo } from '@reuters-graphics/graphics-components';
148
+ </script>
149
+
150
+ <!-- Optionally set `height` to adjust scroll height -->
151
+ <Block width="normal">
152
+ <ScrollerVideo src="my-video.mp4" height="500lvh" objectFit="contain" />
153
+ </Block>
154
+ ```
155
+
156
+ ## Responsive videos
157
+
158
+ To show different videos based on the screen width, use the `ScrollerVideo` component with conditional logic that uses a different video source depending on the [window width](https://svelte.dev/docs/svelte/svelte-window).
159
+
160
+ [Demo](?path=/story/components-graphics-scrollervideo--responsive-videos)
161
+
162
+ ```svelte
163
+ <script lang="ts">
164
+ import { ScrollerVideo } from '@reuters-graphics/graphics-components';
165
+
166
+ let width = $state(0);
167
+ </script>
168
+
169
+ <svelte:window bind:innerWidth={width} />
170
+
171
+ {#if width < 600}
172
+ <!-- Video with aspect ratio 9:16 for window width smaller than 600px -->
173
+ <ScrollerVideo src="my-video-sm.mp4" height="500lvh" />
174
+ {:else if width < 1200}
175
+ <!-- Video with aspect ratio 1:1 for window width between 600px and 1200px -->
176
+ <ScrollerVideo src="my-video-md.mp4" height="500lvh" />
177
+ {:else}
178
+ <!-- Video with aspect ratio 16:9 for window width above 1200px -->
179
+ <ScrollerVideo src="my-video-lg.mp4" height="500lvh" />
180
+ {/if}
181
+ ```
182
+
183
+ ## Embeds
184
+
185
+ Setting `embedded` to `true` will turn `ScrollerVideo` into an embeddable version, where the video autoplays when the user scrolls upon it. Optionally, you can control the embed video behaviour by passing `embeddedProps` to control the autoplay `delay`, `threshold` for triggering autoplay, and the `duration` of the video.
186
+
187
+ > 💡**TIP:** Another way to recreate the ScrollerVideo experience for embeds is to record the desktop screen with [Scroll Capture](https://chromewebstore.google.com/detail/scroll-capture/egmhoeaacclmanaimofoooiamhpkimkk?hl=en) while scrolling through the video and use that video instead as an HTML video component.
188
+
189
+ [Demo](?path=/story/components-graphics-scrollervideo--embed)
190
+
191
+ ```svelte
192
+ <script lang="ts">
193
+ import { ScrollerVideo } from '@reuters-graphics/graphics-components';
194
+
195
+ let embedded = $state(true); // Set to true to enable embedded mode
196
+ </script>
197
+
198
+ <ScrollerVideo
199
+ src="my-video.mp4"
200
+ {embedded}
201
+ embeddedProps={{
202
+ delay: 200, // Optional: Delay before autoplay starts. Defaults to 200ms.
203
+ threshold: 0.5, // Optional: Threshold for triggering the autoplay. Defaults to 0.5.
204
+ duration: 5000, // Optional: Defaults to the duration of the video.
205
+ }}
206
+ />
207
+ ```
208
+
209
+ ## Autoplay
210
+
211
+ The `autoplay` option combines the autoplay and scrollytelling experience. If set to `true`, the video will start playing automatically when the component is mounted, but switch to scrollytelling when the user starts scrolling. The scroll height is calculated based on how much of the video remains, which means that if the user lets the video autoplay to near the end, the user would only have to scroll through a small height to get to the end. If the user lets the video autoplay to the end, there will be no scrolling effect.
212
+
213
+ [Demo](?path=/story/components-graphics-scrollervideo--autoplay)
214
+
215
+ ```svelte
216
+ <script lang="ts">
217
+ import { ScrollerVideo } from '@reuters-graphics/graphics-components';
218
+ </script>
219
+
220
+ <ScrollerVideo src="my-video.mp4" autoplay={true} />
221
+ ```
222
+
223
+ ## Time-based text foregrounds with ArchieML
224
+
225
+ The `ScrollerVideo` component can also be used to display text as foregrounds at specific times in the video. To do so, use the `text` prop in `ScrollerVideoForeground` component.
226
+
227
+ [Demo](?path=/story/components-graphics-scrollervideo--archie-ml-foregrounds)
228
+
229
+ With the graphics kit, you'll likely get your text and prop values from an ArchieML doc...
230
+
231
+ ```yaml
232
+ # ArchieML doc
233
+
234
+ [blocks]
235
+ type: scroller-video
236
+ id: alps-scroller
237
+ src: videos/alps.mp4
238
+ height: 800lvh
239
+
240
+ # Array of foregrounds
241
+ [.foregrounds]
242
+ startTime: 3 # When in the video to start showing the foreground
243
+ endTime: 7 # When to stop showing the foreground
244
+ width: normal # text container width
245
+ position: bottom center # Position of the text. Optional; defaults to 'center center'. Must be a combination of `top/bottom/center center/left/right`
246
+ backgroundColour: rgba(0, 0, 0, 0.8) # Optional; defaults to white
247
+ text: #### The Alps
248
+ The Alps stretch across eight countries: France, Switzerland, Italy, Monaco, Liechtenstein, Austria, Germany, and Slovenia, covering about 1,200 kilometers (750 miles).
249
+ :end
250
+
251
+ startTime: 9
252
+ endTime: 12
253
+ width: normal
254
+ position: bottom center
255
+ backgroundColour: rgba(0, 0, 0, 0.8)
256
+ text: Mont Blanc, standing at 4,809 meters (15,777 feet), is the highest peak in the Alps and Western Europe, though there's ongoing debate between France and Italy about exactly where the summit lies.
257
+ :end
258
+
259
+ startTime: 16
260
+ endTime: 20
261
+ width: normal
262
+ position: bottom center
263
+ backgroundColour: rgba(0, 0, 0, 0.8)
264
+ text: #### History
265
+ The Alps were formed around **65 million years** ago when the African and Eurasian tectonic plates collided, pushing the land upward. Over 14 million people live in the Alpine region, with tourism supporting approximately 120 million visitors annually.
266
+ :end
267
+ []
268
+ []
269
+ ```
270
+
271
+ ... which you'll parse out of a ArchieML block object before passing to the `ScrollerVideo` and `ScrollerVideoForeground` components.
272
+
273
+ ```svelte
274
+ <script lang="ts">
275
+ import {
276
+ ScrollerVideo,
277
+ ScrollerVideoForeground,
278
+ } from '@reuters-graphics/graphics-components';
279
+ import { assets } from '$app/paths'; // 👈 If using in the graphics kit...
280
+ </script>
281
+
282
+ {#each content.blocks as block}
283
+ <!-- Inside the content.blocks for loop... -->
284
+ {#if block.type == 'scroller-video'}
285
+ <ScrollerVideo
286
+ id={block.id}
287
+ src={`${assets}/${block.src}`}
288
+ height={block.height}
289
+ >
290
+ <!-- Loop through foregrounds to add text blurbs that appear/disappear at specific times -->
291
+ {#each block.foregrounds as foreground}
292
+ <ScrollerVideoForeground
293
+ startTime={parseFloat(foreground.startTime)}
294
+ endTime={parseFloat(foreground.endTime)}
295
+ width={foreground.width}
296
+ position={foreground.position}
297
+ backgroundColour={foreground.backgroundColour}
298
+ text={foreground.text}
299
+ />
300
+ {/each}
301
+ </ScrollerVideo>
302
+ {/if}
303
+ {/each}
304
+ ```
305
+
306
+ ## Time-based component foregrounds with ArchieML
307
+
308
+ The `ScrollerVideo` component can also be used to display components, such as `Headline` or ai2svelte files, as foregrounds at specific times in the video. To do so, use the `Foreground` prop in `ScrollerVideoForeground` component.
309
+
310
+ > **IMPORTANT❗**: When layering ai2svelte files over a video, the aspect ratio of the ai2svelte graphics should match that of the video. If the ai2svelte graphic is responsive and has, for example, small, medium and large versions — which is generally the case — make sure to also render small, medium and large versions of the video at the appropriate screen sizes. See [Responsive videos](#responsive-videos) for more details.
311
+
312
+ [Demo](?path=/story/components-graphics-scrollervideo--component-archie-ml-foregrounds)
313
+
314
+ With the graphics kit, you'll likely get your text and prop values from an ArchieML doc...
315
+
316
+ ```yaml
317
+ # ArchieML doc
318
+
319
+ # Headline
320
+ hed: Wind and waves
321
+ [authors]
322
+ * Jane Doe
323
+ []
324
+ publishTime: 2020-01-01T00:00:00Z
325
+ startTime: 0 # When in the video to start showing the headline
326
+ endTime: 0.3 # When to stop showing the headline
327
+
328
+ [blocks]
329
+ type: scroller-video
330
+ id: my-scroller-video
331
+ height: 800lvh
332
+
333
+ # Adjust prop names as needed
334
+ srcSm: videos/my-video-sm.mp4
335
+ srcMd: videos/my-video-md.mp4
336
+ srcLg: videos/my-video-lg.mp4
337
+
338
+ # Array of foregrounds
339
+ [.foregrounds]
340
+ startTime: 0.3 # When in the video to start showing the foreground
341
+ endTime: 2.2 # When to stop showing the foreground
342
+ width: fluid # foreground container width
343
+ Foreground: Foreground1 # Name of the ai2svelte component to render
344
+
345
+ startTime: 2.2
346
+ endTime: 3.2
347
+ width: fluid
348
+ Foreground: Foreground2
349
+
350
+ startTime: 3.2
351
+ endTime: 4.5
352
+ width: fluid
353
+ Foreground: Foreground3
354
+
355
+ startTime: 6.5
356
+ endTime: 8
357
+ width: fluid
358
+ Foreground: Foreground4
359
+ []
360
+ []
361
+ ```
362
+
363
+ ... which you'll parse out of a ArchieML block object before passing to the `ScrollerVideo` and `ScrollerVideoForeground` components.
364
+
365
+ ```svelte
366
+ <script lang="ts">
367
+ import { assets } from '$app/paths'; // 👈 If using in the graphics kit...
368
+ import {
369
+ Headline,
370
+ GraphicBlock,
371
+ ScrollerVideo,
372
+ Foreground,
373
+ } from '@reuters-graphics/graphics-components';
374
+
375
+ // Foreground ai2svelte components
376
+ import Foreground1 from './ai2svelte/foreground1.svelte';
377
+ import Foreground2 from './ai2svelte/foreground2.svelte';
378
+ import Foreground3 from './ai2svelte/foreground3.svelte';
379
+ import Foreground4 from './ai2svelte/foreground4.svelte';
380
+
381
+ // Add your imported foreground ai2svelte charts to this object
382
+ const aiChartsForeground = {
383
+ Foreground1,
384
+ Foreground2,
385
+ Foreground3,
386
+ Foreground4,
387
+ };
388
+
389
+ // Window width for responsive videos
390
+ let width = $state(1);
391
+ </script>
392
+
393
+ <svelte:window bind:innerWidth={width} />
394
+
395
+ <!-- Loop through content blocks... -->
396
+ {#each content.blocks as block}
397
+ {#if block.type == 'scroller-video'}
398
+ <!-- ScrollVideo snippet to render responsive videos -->
399
+ {#snippet ScrollVideo(height: string, src: string)}
400
+ <ScrollerVideo id={block.id} {height} {src}>
401
+ <!-- Headline component as foreground -->
402
+ <ScrollerVideoForeground
403
+ startTime={parseFloat(content.startTime)}
404
+ endTime={parseFloat(content.endTime)}
405
+ >
406
+ <Headline
407
+ hed={content.hed}
408
+ authors={content.authors}
409
+ publishTime={new Date(content.publishTime).toISOString()}
410
+ />
411
+ </ScrollerVideoForeground>
412
+
413
+ <!-- Loop through block.foregrounds to render each foreground component -->
414
+ {#each block.foregrounds as foreground}
415
+ <ScrollerVideoForeground
416
+ startTime={parseFloat(foreground.startTime)}
417
+ endTime={parseFloat(foreground.endTime)}
418
+ width={foreground.width}
419
+ Foreground={aiChartsForeground[
420
+ foreground.foreground as keyof typeof aiChartsForeground
421
+ ]}
422
+ />
423
+ {/each}
424
+ </ScrollerVideo>
425
+ {/snippet}
426
+
427
+ <!-- Render the ScrollVideo snippet for different screen sizes -->
428
+ {#if width < 600}
429
+ {@render ScrollVideo(block.height, `${assets}/${block.srcSm}`)}
430
+ {:else if width < 1200}
431
+ {@render ScrollVideo(block.height, `${assets}/${block.srcMd}`)}
432
+ {:else}
433
+ {@render ScrollVideo(block.height, `${assets}/${block.srcLg}`)}
434
+ {/if}
435
+ {/if}
436
+ {/each}
437
+ ```
438
+
439
+ ## Using with `ScrollerBase`
440
+
441
+ The `ScrollerVideo` component can be used inside the [ScrollerBase](?path=/story/components-graphics-scrollerbase--docs) component to add foreground content. This allows for a foreground that scrolls up and down over the video, instead of fading in and out at specific times.
442
+
443
+ > **Note**: To use `ScrollerVideo` with `ScrollerBase`, set `trackScroll` to `false` and pass the bindable prop `progress` from `ScrollerBase` as `videoPercentage` to `ScrollerVideo`.
444
+
445
+ [Demo](?path=/story/components-graphics-scrollervideo--scroller-base)
446
+
447
+ ```svelte
448
+ <script lang="ts">
449
+ import {
450
+ ScrollerVideo,
451
+ ScrollerBase,
452
+ } from '@reuters-graphics/graphics-components';
453
+
454
+ // Pass `progress` as `videoPercentage` to ScrollerVideo
455
+ let progress = $state(0);
456
+ </script>
457
+
458
+ <ScrollerBase bind:progress query="div.step-foreground-container">
459
+ {#snippet backgroundSnippet()}
460
+ <!-- Pass bindable prop `progress` as `videoPercentage` and set `trackScroll` to `false` -->
461
+ <ScrollerVideo
462
+ src="my-video.mp4"
463
+ height="100lvh"
464
+ videoPercentage={Math.min(1, Math.max(progress, 0))}
465
+ trackScroll={false}
466
+ transitionSpeed={20}
467
+ />
468
+ {/snippet}
469
+ {#snippet foregroundSnippet()}
470
+ <!-- Add custom foreground HTML or component -->
471
+ <div class="step-foreground-container">
472
+ <h3 class="text-center">Step 1</h3>
473
+ </div>
474
+ <div class="step-foreground-container">
475
+ <h3 class="text-center">Step 2</h3>
476
+ </div>
477
+ <div class="step-foreground-container">
478
+ <h3 class="text-center">Step 3</h3>
479
+ </div>
480
+ {/snippet}
481
+ </ScrollerBase>
482
+
483
+ <style lang="scss">
484
+ .step-foreground-container {
485
+ height: 100lvh;
486
+ width: 50%;
487
+ padding: 1em;
488
+ margin: auto;
489
+
490
+ h3 {
491
+ display: flex;
492
+ align-items: center;
493
+ justify-content: center;
494
+ height: 100%;
495
+ color: white;
496
+ }
497
+ }
498
+ </style>
499
+ ```
500
+
501
+ ## Advanced usecases
502
+
503
+ Using the methods attached to the bindable prop `scrollerVideo` allows for advanced customisation of the scroll video behaviour. For example, you can create a looping video that plays a specific section of the video repeatedly, or jump to a specific time in the video when the user scrolls to a certain point.
504
+
505
+ This code below would make the video smoothly jump to the halfway point of the video. Setting `jump` to `true` will make the video jump to the specified percentage abruptly:
506
+
507
+ ```js
508
+ scrollerVideo.setVideoPercentage(
509
+ 0.5, // progress set to 50%
510
+ {
511
+ transitionSpeed: 12, // playback rate for the video
512
+ jump: false, // flag to change transition video abruptly
513
+ easing: (t) => t, // linear easing. Can also pass d3 easing functions - d3.easeLinear
514
+ }
515
+ );
516
+ ```
517
+
518
+ > **Note**: When using these methods, it's recommended to set `trackScroll` to `false` to avoid video playback on scroll and pass functions to the `onReady` prop to ensure that the video is ready before calling any methods on it.
519
+
520
+ Here is a demo that uses `ScrollerVideo` with `ScrollerBase` to make the video jump to the start or the end of the video depending on what step of the scroller the user is on.
521
+
522
+ [Demo](?path=/story/components-graphics-scrollervideo--advanced)
523
+
524
+ ```svelte
525
+ <script lang="ts">
526
+ import {
527
+ ScrollerVideo,
528
+ ScrollerBase,
529
+ type ScrollerVideoInstance,
530
+ } from '@reuters-graphics/graphics-components';
531
+ import { onDestroy } from 'svelte';
532
+
533
+ let scrollerVideo: ScrollerVideoInstance | undefined = $state(undefined);
534
+ let animationFrame = $state(0);
535
+ let index = $state(0); // index for the current step in ScrollerBase
536
+
537
+ // If ScrollerBase is on index 0, jump to the start of the video.
538
+ // Otherwise, jump to 1, or 100% (the end), of the video.
539
+ function jumpVideo() {
540
+ if (index === 0) {
541
+ scrollerVideo?.setVideoPercentage(0, {
542
+ jump: false, // Eases the jump
543
+ });
544
+ } else {
545
+ scrollerVideo?.setVideoPercentage(1, {
546
+ jump: false,
547
+ });
548
+ }
549
+ }
550
+ </script>
551
+
552
+ <ScrollerBase bind:index query="div.step-foreground-container">
553
+ <!-- ScrollerVideo as background -->
554
+ {#snippet backgroundSnippet()}
555
+ <!-- Pass `jumpVideo` to `onReady` and set `trackScroll` to `false` -->
556
+ <ScrollerVideo
557
+ bind:scrollerVideo
558
+ src={Tennis}
559
+ height="100lvh"
560
+ trackScroll={false}
561
+ showDebugInfo
562
+ onReady={jumpVideo}
563
+ />
564
+ {/snippet}
565
+
566
+ <!-- Simple text foregrounds -->
567
+ {#snippet foregroundSnippet()}
568
+ <div class="step-foreground-container">
569
+ <h3 class="text-center">Index {index}</h3>
570
+ </div>
571
+ <div class="step-foreground-container">
572
+ <h3 class="text-center">Index {index}</h3>
573
+ </div>
574
+ {/snippet}
575
+ </ScrollerBase>
576
+ ```
@@ -0,0 +1,44 @@
1
+ # SearchInput
2
+
3
+ **Category:** Components/Controls/SearchInput
4
+
5
+ **Import:** `import { SearchInput } from '@reuters-graphics/graphics-components'`
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Default | Required | Description |
10
+ |------|------|---------|:--------:|-------------|
11
+ | `searchPlaceholder` | `string` | `'Search...'` | | The placeholder text that appears in the search box. |
12
+ | `onsearch` | `(newValue: string) => void` | — | | Optional function that runs when the input value changes. |
13
+
14
+ ## Examples
15
+
16
+ ### Demo
17
+
18
+ ```svelte
19
+ <SearchInput onsearch={handleSearchInput} />
20
+ ```
21
+
22
+ ## Documentation
23
+
24
+ # SearchInput
25
+
26
+ The `SearchInput` component creates a search bar.
27
+
28
+ ```svelte
29
+ <script>
30
+ import { SearchInput } from '@reuters-graphics/graphics-components';
31
+
32
+ function filterData(newSearchText: string) {
33
+ /** This function would typically filter a dataset based on the search input.*/
34
+ console.log('Filtering data with:', newSearchText);
35
+ }
36
+ function handleSearchInput(newSearchText: string) {
37
+ /** Here's where you might update a variable,
38
+ filter a dataset or make an API call based on the user's input.*/
39
+ filterData(newSearchText);
40
+ }
41
+ </script>
42
+
43
+ <SearchInput onsearch={handleSearchInput} />
44
+ ```
@@ -0,0 +1,78 @@
1
+ # ShareBar
2
+
3
+ ShareBar shows a row of share buttons (X, Facebook, LinkedIn, Email, Copy link) and an optional "Purchase Licensing Rights" button, echoing the share toolbar on Reuters.com stories.
4
+
5
+ **Category:** Components/Page furniture/ShareBar
6
+
7
+ **Import:** `import { ShareBar } from '@reuters-graphics/graphics-components'`
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Required | Description |
12
+ |------|------|---------|:--------:|-------------|
13
+ | `url` | `string` | — | | Canonical URL to share. When omitted, the live `window.location.href` is read at click time so a shared link reproduces the reader's current view. |
14
+ | `headline` | `string` | `''` | | Headline used as the share text and email subject. |
15
+ | `licensingUrl` | `string` | `'https://www.reutersagency.com/en/licensereuterscontent/?utm_medium=rcom-article-media&utm_campaign=rcom-rcp-lead'` | | Destination for the "Purchase Licensing Rights" button. |
16
+ | `showLicensing` | `boolean` | `true` | | Hide the "Purchase Licensing Rights" button when false. |
17
+ | `id` | `string` | `''` | | ID on the containing block. |
18
+ | `class` | `string` | `'fmy-8'` | | Extra classes on the containing block. |
19
+
20
+ ## Examples
21
+
22
+ ### Demo
23
+
24
+ ```svelte
25
+ <ShareBar
26
+ url="https://www.reuters.com/graphics/example-story/"
27
+ headline="An example Reuters graphic"
28
+ />
29
+ ```
30
+
31
+ ### Without licensing button
32
+
33
+ ```svelte
34
+ <ShareBar
35
+ url="https://www.reuters.com/graphics/example-story/"
36
+ headline="An example Reuters graphic"
37
+ showLicensing={false}
38
+ />
39
+ ```
40
+
41
+ ### Custom licensing URL
42
+
43
+ ```svelte
44
+ <ShareBar
45
+ url="https://www.reuters.com/graphics/example-story/"
46
+ headline="An example Reuters graphic"
47
+ licensingUrl="https://www.reutersagency.com/en/licensereuterscontent/"
48
+ />
49
+ ```
50
+
51
+ ## Documentation
52
+
53
+ # ShareBar
54
+
55
+ The `ShareBar` component shows a row of share buttons — X, Facebook, LinkedIn, Email and Copy link — alongside an optional **Purchase Licensing Rights** button, echoing the share toolbar on Reuters.com stories.
56
+
57
+ The social buttons open the platform's share dialog in a popup window, Email opens the reader's mail client, and Copy link writes the URL to the clipboard with a brief "Link copied" confirmation. The clipboard copy uses an `execCommand` fallback so it still works inside cross-origin iframes (how Reuters embeds graphics), where the async Clipboard API is blocked.
58
+
59
+ When you don't pass a `url`, the component reads the live `window.location.href` at click time, so a shared link reproduces the reader's current view.
60
+
61
+ ```svelte
62
+ <script>
63
+ import { ShareBar } from '@reuters-graphics/graphics-components';
64
+ </script>
65
+
66
+ <ShareBar
67
+ url="https://www.reuters.com/graphics/example-story/"
68
+ headline="An example Reuters graphic"
69
+ />
70
+ ```
71
+
72
+ ## Without the licensing button
73
+
74
+ Set `showLicensing={false}` to hide the **Purchase Licensing Rights** button and show only the share icons.
75
+
76
+ ```svelte
77
+ <ShareBar headline="An example Reuters graphic" showLicensing={false} />
78
+ ```