@reuters-graphics/graphics-components 3.10.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 +1 -1
@@ -0,0 +1,350 @@
1
+ # Scroller
2
+
3
+ **Category:** Components/Graphics/Scroller
4
+
5
+ **Import:** `import { Scroller } from '@reuters-graphics/graphics-components'`
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Default | Required | Description |
10
+ |------|------|---------|:--------:|-------------|
11
+ | `steps` | `ScrollerStep[]` | — | ✓ | An array of step objects that define the steps in your scroller. Each step object in the array can have: - `background` A background component. **REQUIRED** - `backgroundProps` Optional props for background component. - `foreground` A component or markdown-formatted string. **REQUIRED** - `foregroundProps` Optional props for foreground component. - `altText` Optional alt text for the background, read aloud after the foreground text. You can add it to each step or just to the first step to describe the entire scroller graphic. **RECOMMENDED** |
12
+ | `backgroundWidth` | `ContainerWidth` | `'fluid'` | | Width of the background Options: `normal`, `wide`, `wider`, `widest`, `fluid` |
13
+ | `foregroundPosition` | `ForegroundPosition` | `'middle'` | | Position of the foreground Options: `middle`, `left`, `right`, `left opposite`, `right opposite` |
14
+ | `stackBackground` | `boolean` | `true` | | Whether previous background steps should stack below the current one. - `true` _default_ Background graphics from previous steps will remain visible below the active one, allowing you to stack graphics with transparent backgrounds. - `false` Only the background graphic from the current step will show and backgrounds from previous steps are hidden. |
15
+ | `preload` | `number` | `1` | | How many background steps to load before and after the currently active one, effectively lazy-loading them. Setting to `0` disables lazy-loading and loads all backgrounds at once. |
16
+ | `embedded` | `boolean` | `false` | | Setting to `true` will unroll the scroll experience into a flat layout |
17
+ | `embeddedLayout` | `'fb' \| 'bf'` | `'fb'` | | Layout order when `embedded` is `true`. - `fb` _default_ Foreground then background - `bf` Background then foreground Options: `fb`, `bf` |
18
+ | `threshold` | `number` | `0.5` | | Threshold prop passed to [svelte-scroller](https://github.com/sveltejs/svelte-scroller#parameters) |
19
+ | `top` | `number` | `0` | | Top prop passed to [svelte-scroller](https://github.com/sveltejs/svelte-scroller#parameters) |
20
+ | `bottom` | `number` | `1` | | Bottom prop passed to [svelte-scroller](https://github.com/sveltejs/svelte-scroller#parameters) |
21
+ | `parallax` | `boolean` | `false` | | Parallax prop passed to [svelte-scroller](https://github.com/sveltejs/svelte-scroller#parameters) |
22
+ | `id` | `string` | `''` | | ID of the scroller container |
23
+ | `class` | `string` | `''` | | Set a class to target with SCSS |
24
+ | `index` | `number` | `$bindable(0)` | | The currently active section |
25
+ | `offset` | `number` | `$bindable(0)` | | How far the section has scrolled past the threshold, as a value between 0 and 1 |
26
+ | `progress` | `number` | `$bindable(0)` | | How far the foreground has travelled, where 0 is the top of the foreground crossing top, and 1 is the bottom crossing bottom |
27
+
28
+ ## Examples
29
+
30
+ ### Demo
31
+
32
+ ```svelte
33
+ <Scroller
34
+ steps={/* array — see Props/Types for full type */}
35
+ foregroundPosition="middle"
36
+ backgroundWidth="fluid"
37
+ />
38
+ ```
39
+
40
+ ### ArchieML and ai2svelte
41
+
42
+ ```svelte
43
+ <Scroller
44
+ id={docBlock.id}
45
+ foregroundPosition={docBlock.foregroundPosition}
46
+ stackBackground={docBlock.stackBackground === 'true'}
47
+ steps={docBlock.steps.map((step) => ({
48
+ background: step.background,
49
+ foreground: step.foreground,
50
+ altText: step.altText,
51
+ }))}
52
+ />
53
+ ```
54
+
55
+ ### Custom foreground
56
+
57
+ ```svelte
58
+ <Scroller steps={/* array — see Props/Types for full type */} />
59
+ ```
60
+
61
+ ### Custom foreground with ArchiemL
62
+
63
+ ```svelte
64
+ <Scroller
65
+ id={docBlockCustomForeground.id}
66
+ foregroundPosition={docBlockCustomForeground.foregroundPosition}
67
+ stackBackground={docBlockCustomForeground.stackBackground === 'true'}
68
+ steps={docBlockCustomForeground.steps.map((step) => ({
69
+ background: step.background,
70
+ foreground: step.foreground,
71
+ altText: step.altText,
72
+ }))}
73
+ />
74
+ ```
75
+
76
+ ## Documentation
77
+
78
+ # Scroller
79
+
80
+ The `Scroller` component creates a basic scrollytelling graphic with layout options.
81
+
82
+ This component is designed to handle most common layouts for scrollytelling. To make something more complex, customise [ScrollerBase](?path=/story/components-graphics-scrollerbase--docs), which is a Svelte 5 version of the [svelte-scroller](https://github.com/sveltejs/svelte-scroller).
83
+
84
+ [Demo](?path=/story/components-graphics-scroller--demo)
85
+
86
+ ```svelte
87
+ <script>
88
+ import { Scroller } from '@reuters-graphics/graphics-components';
89
+
90
+ import MyBackground from './MyBackground.svelte'; // Your own background component
91
+
92
+ // Array of step objects that define the steps in your scroller.
93
+ const steps = [
94
+ {
95
+ background: MyBackground,
96
+ backgroundProps: { colour: 'red' }, // Optional props for your background component
97
+ foreground: '#### Step 1\n\nLorem ipsum red',
98
+ altText: 'Red background',
99
+ },
100
+ {
101
+ background: MyBackground,
102
+ backgroundProps: { colour: 'blue' },
103
+ foreground: '#### Step 2\n\nLorem ipsum blue',
104
+ altText: 'Blue background',
105
+ },
106
+ {
107
+ background: MyBackground,
108
+ backgroundProps: { colour: 'green' },
109
+ foreground: '#### Step 3\n\nLorem ipsum green',
110
+ altText: 'Green background',
111
+ },
112
+ ];
113
+ </script>
114
+
115
+ <Scroller {steps} foregroundPosition="middle" backgroundWidth="fluid" />
116
+ ```
117
+
118
+ ## Using with ArchieML and ai2svelte
119
+
120
+ [Demo](?path=/story/components-graphics-scroller--archie-ml)
121
+
122
+ In your graphics kit project, import your ai2svelte graphics in `App.svelte` and add them to the `aiCharts` object:
123
+
124
+ ```svelte
125
+ <!-- App.svelte -->
126
+ <script>
127
+ import AiMap1 from './ai2svelte/my-map-1.svelte';
128
+ import AiMap2 from './ai2svelte/my-map-2.svelte';
129
+ import AiMap3 from './ai2svelte/my-map-3.svelte';
130
+
131
+ import content from '$locales/en/content.json';
132
+
133
+ // Graphics kit only
134
+ import { assets } from '$app/paths'; // 👈 If using in the graphics kit...
135
+ import { truthy } from '$utils/propValidators'; // 👈 If using in the graphics kit...
136
+
137
+ const aiCharts = {
138
+ AiMap1,
139
+ AiMap2,
140
+ AiMap3,
141
+ // Other charts...
142
+ };
143
+ </script>
144
+ ```
145
+
146
+ Then add the following structure to your ArchieML doc, making sure that the names of your charts in the `aiCharts` object match the names of each step's `background` in the ArchieML doc:
147
+
148
+ ```yaml
149
+ # ArchieML doc
150
+ [blocks]
151
+ type: ai-scroller
152
+ id: my-map-scroller
153
+ width: fluid
154
+ foregroundPosition: right
155
+ stackBackground: true
156
+
157
+ # Array of step objects
158
+ [.steps]
159
+ background: AiMap1
160
+ foreground: #### Step 1
161
+
162
+ Here's where something happend.
163
+ :end
164
+ altText: A map showing the Upper West side in New York City.
165
+
166
+ Can add paragraphs of alt text if you want to break up sentences.
167
+ :end
168
+
169
+ background: AiMap2
170
+ foreground: #### Step 2
171
+
172
+ Something happened on some street...
173
+ :end
174
+ altText: The same map now highlights 98th Street.
175
+ :end
176
+
177
+ background: AiMap3
178
+ foreground: #### Step 3
179
+
180
+ ... and now there are multiple protests.
181
+ :end
182
+ altText: The same map now highlights three locations near 98th Street where something particulary important happened.
183
+ :end
184
+ []
185
+ []
186
+ ```
187
+
188
+ Then parse the relevant ArchieML block object before passing to the `Scroller` component.
189
+
190
+ ```svelte
191
+ <!-- App.svelte -->
192
+ {#each content.blocks as block}
193
+ {#if block.type === 'ai-scroller'}
194
+ <Scroller
195
+ id={block.id}
196
+ backgroundWidth={block.backgroundWidth}
197
+ foregroundPosition={block.foregroundPosition}
198
+ stackBackground={truthy(block.stackBackground)}
199
+ steps={block.steps.map((step) => ({
200
+ background: aiCharts[step.background],
201
+ backgroundProps: { assetsPath: assets || '/' },
202
+ foreground: step.foreground,
203
+ altText: step.altText,
204
+ }))}
205
+ />
206
+ {/if}
207
+ {/each}
208
+ ```
209
+
210
+ > **Note:** Some props, like `stackBackground`, expect boolean values. If you're using the graphics kit, use the `truthy()` util function to convert a string value to a boolean.
211
+
212
+ > **Note:** In the graphics kit, the image source paths in ai2svelte components have to be fixed by passing `assets` to each step object, like in the example above.
213
+
214
+ ## Custom foreground
215
+
216
+ [Demo](?path=/story/components-graphics-scroller--custom-foreground)
217
+
218
+ Instead of just text, you can use components as foregrounds, and optionally pass props to it.
219
+
220
+ If you're customising your own foreground component, remember to add alt text that describes the background graphic.
221
+
222
+ ```svelte
223
+ <script>
224
+ import MyBackground from './MyBackground.svelte'; // Your own background component
225
+ import MyInteractiveForeground from './MyInteractiveForeground.svelte'; // Your custom foreground component
226
+
227
+ const steps = [
228
+ {
229
+ background: MyBackground,
230
+ backgroundProps: { colour: 'red' }, // Props for your background component, if needed
231
+ foreground: MyInteractiveForeground, // Custom foreground component
232
+ },
233
+ {
234
+ background: MyBackground,
235
+ backgroundProps: { colour: 'blue' },
236
+ foreground: '#### Step 2\n\nLorem ipsum blue', // You can still add a markdown string as foreground; you can mix and match
237
+ },
238
+ {
239
+ background: MyBackground,
240
+ backgroundProps: { colour: 'green' },
241
+ foreground: MyInteractiveForeground,
242
+ foregroundProps: { count: 100 }, // Props for your custom foreground component, if needed
243
+ },
244
+ ];
245
+ </script>
246
+
247
+ <Scroller {steps} />
248
+ ```
249
+
250
+ ## Custom foreground with ArchieML
251
+
252
+ [Demo](?path=/story/components-graphics-scroller--customforeground-archie-ml)
253
+
254
+ You can use custom foreground components with ArchieML with a few additional steps.
255
+
256
+ In your graphics kit project's `App.svelte`, import your custom foregroud components and add them to a `foregroundComponents` object, just as you import ai2svelte background graphics and add them to the `aiCharts` object:
257
+
258
+ ```svelte
259
+ <!-- App.svelte -->
260
+ <script>
261
+ import content from '$locales/en/content.json';
262
+
263
+ // Background ai2svelte graphics
264
+ import AiMap1 from './ai2svelte/my-map-1.svelte';
265
+ import AiMap2 from './ai2svelte/my-map-2.svelte';
266
+ import AiMap3 from './ai2svelte/my-map-3.svelte';
267
+
268
+ // Foreground components, which can be ai2svelte or not.
269
+ import Foreground1 from './ai2svelte/my-foreground-1.svelte';
270
+
271
+ // Graphics kit only
272
+ import { assets } from '$app/paths'; // 👈 If using in the graphics kit...
273
+ import { truthy } from '$utils/propValidators'; // 👈 If using in the graphics kit...
274
+
275
+ // Background ai2svelte graphics components
276
+ const aiCharts = {
277
+ AiMap1,
278
+ AiMap2,
279
+ AiMap3,
280
+ // Other charts...
281
+ };
282
+
283
+ // Foreground components
284
+ const foregroundComponents = {
285
+ Foreground1,
286
+ // Other components...
287
+ };
288
+ </script>
289
+ ```
290
+
291
+ Then add the following structure to your ArchieML doc, making sure that the names of your charts in the `aiCharts` and `foregroundComponents` objects match the names of each step's `background` and `foreground` in the ArchieML doc:
292
+
293
+ ```yaml
294
+ # ArchieML doc
295
+ [blocks]
296
+ type: ai-scroller
297
+ id: my-map-scroller
298
+ foregroundPosition: left
299
+ stackBackground: true
300
+
301
+ # Array of step objects
302
+ [.steps]
303
+ background: AiMap1
304
+ # You can still use a markdown string even if other step/s use a custom foreground component
305
+ foreground: #### Step 1
306
+
307
+ Here's where something happend.
308
+ :end
309
+ altText: A map showing the Upper West side in New York City.
310
+ :end
311
+
312
+ background: AiMap2
313
+ foreground: Foreground1 # The name of your custom foreground component
314
+ altText: The same map now highlights 98th Street.
315
+ :end
316
+ background: AiMap3
317
+ foreground: #### Step 3
318
+
319
+ ... and now there are multiple protests.
320
+ :end
321
+ altText: The same map now highlights three locations near 98th Street where something particulary important happened.
322
+ :end
323
+ []
324
+ []
325
+ ```
326
+
327
+ Then parse the relevant ArchieML block object before passing to the `Scroller` component.
328
+
329
+ ```svelte
330
+ <!-- App.svelte -->
331
+ {#each content.blocks as block}
332
+ {#if block.type === 'ai-scroller'}
333
+ <Scroller
334
+ id={block.id}
335
+ backgroundWidth={block.width}
336
+ foregroundPosition={block.foregroundPosition}
337
+ stackBackground={truthy(block.stackBackground)}
338
+ steps={block.steps.map((step) => ({
339
+ background: aiCharts[step.background],
340
+ backgroundProps: { assetsPath: assets || '/' },
341
+ foreground: foregroundComponents[step.foreground] || step.foreground,
342
+ foregroundProps: { assetsPath: assets || '/' },
343
+ altText: step.altText,
344
+ }))}
345
+ />
346
+ {/if}
347
+ {/each}
348
+ ```
349
+
350
+ > **Note:** You only need to pass `foregroundProps: { assetsPath: assets || '/' }` in the graphics kit if your foreground components are ai2svelte graphicss.
@@ -0,0 +1,104 @@
1
+ # ScrollerBase
2
+
3
+ **Category:** Components/Graphics/ScrollerBase
4
+
5
+ **Import:** `import { ScrollerBase } from '@reuters-graphics/graphics-components'`
6
+
7
+ ## Props
8
+
9
+ | Prop | Type | Default | Required | Description |
10
+ |------|------|---------|:--------:|-------------|
11
+ | `top` | `number` | `0` | | Config |
12
+ | `bottom` | `number` | `1` | | The inverse of top — once the bottom of the foreground passes this point, the background becomes unfixed. **Value between 0 and 1.** |
13
+ | `threshold` | `number` | `0.5` | | Once a section crosses this point, it becomes 'active'. **Value between 0 and 1.** |
14
+ | `query` | `string` | `'div.step-foreground-container'` | | A CSS selector that describes the individual sections of your foreground. |
15
+ | `parallax` | `boolean` | `false` | | If `true`, the background will scroll such that the bottom edge reaches the bottom at the same time as the foreground. This effect can be unpleasant for people with high motion sensitivity, so use it advisedly. |
16
+ | `backgroundSnippet` | `Snippet` | — | ✓ | The background snippet. |
17
+ | `foregroundSnippet` | `Snippet` | — | ✓ | The foreground snippet. |
18
+ | `index` | `number` | `$bindable(0)` | | Bindings |
19
+ | `offset` | `number` | `$bindable(0)` | | How far the section has scrolled past the threshold, as a value between 0 and 1. **Bindable**. |
20
+ | `progress` | `number` | `$bindable(0)` | | How far the foreground has travelled, where 0 is the top of the foreground crossing top, and 1 is the bottom crossing bottom. **Bindable**. |
21
+ | `count` | `number` | `$bindable(0)` | | Number of sections |
22
+ | `visible` | `boolean` | `$bindable(false)` | | Whether the foreground is visible |
23
+
24
+ ## Examples
25
+
26
+ ### Demo
27
+
28
+ ```svelte
29
+ <ScrollerDemo />
30
+ ```
31
+
32
+ ## Documentation
33
+
34
+ # ScrollerBase
35
+
36
+ The `ScrollerBase` component powers the [`Scroller` component](?path=/story/components-graphics-scroller--docs), which creates a basic storytelling graphic with preset layout options. `ScrollerBase` contains the bare minimum code necessary for a scrollytelling section, and allows for customisation beyond what the [`Scroller` component](?path=/story/components-graphics-scroller--docs) allows.
37
+
38
+ `ScrollerBase` is a Svelte 5 version of the [svelte-scroller](https://github.com/sveltejs/svelte-scroller).
39
+
40
+ > **Important❗:** Make sure the HTML element containing each foreground is a div with the class `step-foreground-container`. If you're modifying this to something else, pass the appropriate selector to the `query` prop.
41
+
42
+ [Demo](?path=/story/components-graphics-scrollerbase--demo)
43
+
44
+ ```svelte
45
+ <script lang="ts">
46
+ import { ScrollerBase } from '@reuters-graphics/graphics-components';
47
+
48
+ // Optional: Bind your own variables to use them in your code.
49
+ let count = $state(1);
50
+ let index = $state(0);
51
+ let offset = $state(0);
52
+ let progress = $state(0);
53
+ let top = $state(0.1);
54
+ let threshold = $state(0.5);
55
+ let bottom = $state(0.9);
56
+ </script>
57
+
58
+ <ScrollerBase
59
+ {top}
60
+ {threshold}
61
+ {bottom}
62
+ bind:count
63
+ bind:index
64
+ bind:offset
65
+ bind:progress
66
+ query="div.step-foreground-container"
67
+ >
68
+ {#snippet backgroundSnippet()}
69
+ <!-- Add custom background HTML or component -->
70
+ <p class="mb-0">
71
+ Current step: <strong>{index + 1}/{count}</strong>
72
+ </p>
73
+ <progress class="mb-4" value={(index + 1) / count}></progress>
74
+
75
+ <p class="mb-0">Offset in current step</p>
76
+ <progress class="mb-4" value={offset}></progress>
77
+
78
+ <p class="mb-0">Total progress</p>
79
+ <progress class="mb-4" value={progress}></progress>
80
+ {/snippet}
81
+ {#snippet foregroundSnippet()}
82
+ <!-- Add custom foreground HTML or component -->
83
+ <div class="step-foreground-container">Step 1</div>
84
+ <div class="step-foreground-container">Step 2</div>
85
+ <div class="step-foreground-container">Step 3</div>
86
+ <div class="step-foreground-container">Step 4</div>
87
+ <div class="step-foreground-container">Step 5</div>
88
+ {/snippet}
89
+ </ScrollerBase>
90
+
91
+ <style lang="scss">
92
+ @use '@reuters-graphics/graphics-components/dist/scss/mixins' as mixins;
93
+
94
+ .step-foreground-container {
95
+ height: 100vh;
96
+ width: 50%;
97
+ background-color: rgba(0, 0, 0, 0.2);
98
+ padding: 1em;
99
+ margin: 0 0 2em 0;
100
+ position: relative;
101
+ left: 50%;
102
+ }
103
+ </style>
104
+ ```