@financial-times/cp-content-pipeline-ui 6.4.6 → 6.5.0

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 (49) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/lib/client.d.ts +1 -0
  3. package/lib/client.js +3 -1
  4. package/lib/client.js.map +1 -1
  5. package/lib/components/Clip/client/index.d.ts +1 -0
  6. package/lib/components/Clip/client/index.js +1 -0
  7. package/lib/components/Clip/client/index.js.map +1 -1
  8. package/lib/components/Clip/client/progressBar.d.ts +0 -1
  9. package/lib/components/Clip/client/progressBar.js +10 -8
  10. package/lib/components/Clip/client/progressBar.js.map +1 -1
  11. package/lib/components/Clip/test/snapshot.spec.js +2 -0
  12. package/lib/components/Clip/test/snapshot.spec.js.map +1 -1
  13. package/lib/components/Flourish/client/index.d.ts +2 -0
  14. package/lib/components/Flourish/client/index.js +16 -0
  15. package/lib/components/Flourish/client/index.js.map +1 -0
  16. package/lib/components/Flourish/index.d.ts +16 -3
  17. package/lib/components/Flourish/index.js +21 -4
  18. package/lib/components/Flourish/index.js.map +1 -1
  19. package/lib/components/Flourish/test/snapshot.spec.d.ts +1 -0
  20. package/lib/components/Flourish/test/snapshot.spec.js +57 -0
  21. package/lib/components/Flourish/test/snapshot.spec.js.map +1 -0
  22. package/lib/components/Layout/index.d.ts +9 -3
  23. package/lib/components/Layout/index.js +7 -1
  24. package/lib/components/Layout/index.js.map +1 -1
  25. package/lib/components/Topper/index.d.ts +1 -2
  26. package/lib/components/Topper/index.js +6 -0
  27. package/lib/components/Topper/index.js.map +1 -1
  28. package/lib/stories/Topper.stories.d.ts +9 -0
  29. package/lib/stories/Topper.stories.js +23 -0
  30. package/lib/stories/Topper.stories.js.map +1 -0
  31. package/lib/stories/content.d.ts +65 -0
  32. package/lib/stories/content.js +82 -0
  33. package/lib/stories/content.js.map +1 -0
  34. package/package.json +6 -5
  35. package/src/client.ts +1 -0
  36. package/src/components/Clip/client/index.ts +2 -0
  37. package/src/components/Clip/client/progressBar.ts +12 -8
  38. package/src/components/Clip/test/snapshot.spec.tsx +2 -0
  39. package/src/components/Flourish/client/index.ts +17 -0
  40. package/src/components/Flourish/client/main.scss +38 -0
  41. package/src/components/Flourish/index.tsx +55 -6
  42. package/src/components/Flourish/test/__snapshots__/snapshot.spec.tsx.snap +310 -0
  43. package/src/components/Flourish/test/snapshot.spec.tsx +115 -0
  44. package/src/components/Layout/index.tsx +17 -4
  45. package/src/components/Topper/client/main.scss +5 -0
  46. package/src/components/Topper/index.tsx +21 -2
  47. package/src/stories/Topper.stories.tsx +22 -0
  48. package/src/stories/content.tsx +78 -0
  49. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,310 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`Flourish component renders ignoring layout different from full-grid 1`] = `
4
+ <div>
5
+ <div
6
+ class="n-content-layout"
7
+ data-component="flourish"
8
+ >
9
+ <figure
10
+ class="n-content-picture n-content-layout__container"
11
+ >
12
+ <a
13
+ href="#123"
14
+ >
15
+ <picture
16
+ data-asset-type="flourish"
17
+ data-flourish-id="123"
18
+ data-flourish-type="bar"
19
+ >
20
+ <div
21
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
22
+ data-o-component="o-message"
23
+ id="123"
24
+ >
25
+ <div
26
+ class="o-message__container"
27
+ >
28
+ <div
29
+ class="o-message__content"
30
+ >
31
+ <p
32
+ class="o-message__content-main"
33
+ >
34
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
35
+ </p>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ <img
40
+ alt="foo"
41
+ src="https://example.com/image.jpg"
42
+ />
43
+ </picture>
44
+ </a>
45
+ </figure>
46
+ </div>
47
+ </div>
48
+ `;
49
+
50
+ exports[`Flourish component renders with a full-grid layout and fallback image 1`] = `
51
+ <div>
52
+ <div
53
+ class="n-content-layout"
54
+ data-component="flourish"
55
+ data-layout-width="full-grid"
56
+ >
57
+ <figure
58
+ class="n-content-picture n-content-layout__container n-content-picture--wide"
59
+ data-original-image-height="150"
60
+ data-original-image-width="100"
61
+ >
62
+ <a
63
+ href="#123"
64
+ >
65
+ <picture
66
+ data-asset-type="flourish"
67
+ data-flourish-id="123"
68
+ data-flourish-type="bar"
69
+ >
70
+ <div
71
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
72
+ data-o-component="o-message"
73
+ id="123"
74
+ >
75
+ <div
76
+ class="o-message__container"
77
+ >
78
+ <div
79
+ class="o-message__content"
80
+ >
81
+ <p
82
+ class="o-message__content-main"
83
+ >
84
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
85
+ </p>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ <img
90
+ alt="foo"
91
+ src="https://example.com/image.jpg"
92
+ />
93
+ </picture>
94
+ </a>
95
+ </figure>
96
+ </div>
97
+ </div>
98
+ `;
99
+
100
+ exports[`Flourish component renders with an iframe rather than using the embed script to insert it 1`] = `
101
+ <div>
102
+ <div
103
+ class="n-content-layout flourish flourish--iFrame"
104
+ data-component="flourish"
105
+ data-layout-width="full-grid"
106
+ >
107
+ <iframe
108
+ class="flourish__i-frame"
109
+ src="https://flo.uri.sh/visualisation/123/embed?hideTitle=false"
110
+ style="width: 100%;"
111
+ />
112
+ <figure
113
+ class="n-content-picture n-content-layout__container n-content-picture--wide flourish__figure"
114
+ data-original-image-height="150"
115
+ data-original-image-width="100"
116
+ >
117
+ <a
118
+ href="#123"
119
+ >
120
+ <picture
121
+ data-asset-type="flourish-embed"
122
+ data-flourish-id="123"
123
+ data-flourish-type="bar"
124
+ >
125
+ <div
126
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
127
+ data-o-component="o-message"
128
+ id="123"
129
+ >
130
+ <div
131
+ class="o-message__container"
132
+ >
133
+ <div
134
+ class="o-message__content"
135
+ >
136
+ <p
137
+ class="o-message__content-main"
138
+ >
139
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
140
+ </p>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ <img
145
+ alt="foo"
146
+ src="https://example.com/image.jpg"
147
+ />
148
+ </picture>
149
+ </a>
150
+ </figure>
151
+ </div>
152
+ </div>
153
+ `;
154
+
155
+ exports[`Flourish component renders without n-content-layout class for charts not in article body 1`] = `
156
+ <div>
157
+ <div
158
+ class=""
159
+ data-component="flourish"
160
+ data-layout-width="full-grid"
161
+ >
162
+ <figure
163
+ class="n-content-picture n-content-layout__container n-content-picture--wide"
164
+ data-original-image-height="150"
165
+ data-original-image-width="100"
166
+ >
167
+ <a
168
+ href="#123"
169
+ >
170
+ <picture
171
+ data-asset-type="flourish"
172
+ data-flourish-id="123"
173
+ data-flourish-type="bar"
174
+ >
175
+ <div
176
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
177
+ data-o-component="o-message"
178
+ id="123"
179
+ >
180
+ <div
181
+ class="o-message__container"
182
+ >
183
+ <div
184
+ class="o-message__content"
185
+ >
186
+ <p
187
+ class="o-message__content-main"
188
+ >
189
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
190
+ </p>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ <img
195
+ alt="foo"
196
+ src="https://example.com/image.jpg"
197
+ style="width: 100%;"
198
+ />
199
+ </picture>
200
+ </a>
201
+ </figure>
202
+ </div>
203
+ </div>
204
+ `;
205
+
206
+ exports[`does not set aspect ratios when in article body 1`] = `
207
+ <div>
208
+ <div
209
+ class="n-content-layout"
210
+ data-component="flourish"
211
+ data-layout-width="full-grid"
212
+ >
213
+ <figure
214
+ class="n-content-picture n-content-layout__container n-content-picture--wide"
215
+ data-original-image-height="150"
216
+ data-original-image-width="100"
217
+ >
218
+ <a
219
+ href="#123"
220
+ >
221
+ <picture
222
+ data-asset-type="flourish"
223
+ data-flourish-id="123"
224
+ data-flourish-type="bar"
225
+ >
226
+ <div
227
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
228
+ data-o-component="o-message"
229
+ id="123"
230
+ >
231
+ <div
232
+ class="o-message__container"
233
+ >
234
+ <div
235
+ class="o-message__content"
236
+ >
237
+ <p
238
+ class="o-message__content-main"
239
+ >
240
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
241
+ </p>
242
+ </div>
243
+ </div>
244
+ </div>
245
+ <img
246
+ alt="foo"
247
+ src="https://example.com/image.jpg"
248
+ />
249
+ </picture>
250
+ </a>
251
+ </figure>
252
+ </div>
253
+ </div>
254
+ `;
255
+
256
+ exports[`sets the hideTitle param in the iframe url to true when not in article body 1`] = `
257
+ <div>
258
+ <div
259
+ class="flourish flourish--iFrame"
260
+ data-component="flourish"
261
+ data-layout-width="full-grid"
262
+ >
263
+ <iframe
264
+ class="flourish__i-frame"
265
+ src="https://flo.uri.sh/visualisation/123/embed?hideTitle=true"
266
+ style="width: 100%;"
267
+ />
268
+ <figure
269
+ class="n-content-picture n-content-layout__container n-content-picture--wide flourish__figure"
270
+ data-original-image-height="150"
271
+ data-original-image-width="100"
272
+ >
273
+ <a
274
+ href="#123"
275
+ >
276
+ <picture
277
+ data-asset-type="flourish-embed"
278
+ data-flourish-id="123"
279
+ data-flourish-type="bar"
280
+ >
281
+ <div
282
+ class="flourish-disclaimer o-message o-message--alert o-message--neutral"
283
+ data-o-component="o-message"
284
+ id="123"
285
+ >
286
+ <div
287
+ class="o-message__container"
288
+ >
289
+ <div
290
+ class="o-message__content"
291
+ >
292
+ <p
293
+ class="o-message__content-main"
294
+ >
295
+ You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.
296
+ </p>
297
+ </div>
298
+ </div>
299
+ </div>
300
+ <img
301
+ alt="foo"
302
+ src="https://example.com/image.jpg"
303
+ style="width: 100%;"
304
+ />
305
+ </picture>
306
+ </a>
307
+ </figure>
308
+ </div>
309
+ </div>
310
+ `;
@@ -0,0 +1,115 @@
1
+ import React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import Flourish from '../'
4
+
5
+ enum acceptedFormat {
6
+ standard = 'standard',
7
+ }
8
+
9
+ const anImage = {
10
+ id: '123',
11
+ url: 'https://example.com/image.jpg',
12
+ width: 100,
13
+ height: 150,
14
+ format: 'standard' as acceptedFormat,
15
+ sourceSet: [
16
+ {
17
+ url: 'https://example.com/anotherImage.jpg',
18
+ width: 200,
19
+ dpr: 2,
20
+ },
21
+ ],
22
+ }
23
+ describe('Flourish component', () => {
24
+ it('renders with a full-grid layout and fallback image', async () => {
25
+ const { container } = render(
26
+ <Flourish
27
+ type="flourish"
28
+ id="123"
29
+ flourishType="bar"
30
+ description="foo"
31
+ layoutWidth="full-grid"
32
+ fallbackImage={anImage}
33
+ />
34
+ )
35
+ expect(container).toMatchSnapshot()
36
+ })
37
+
38
+ it('renders ignoring layout different from full-grid', async () => {
39
+ const { container } = render(
40
+ <Flourish
41
+ type="flourish"
42
+ id="123"
43
+ flourishType="bar"
44
+ description="foo"
45
+ layoutWidth="whatever"
46
+ fallbackImage={anImage}
47
+ />
48
+ )
49
+ expect(container).toMatchSnapshot()
50
+ })
51
+
52
+ it('renders with an iframe rather than using the embed script to insert it', async () => {
53
+ const iFrame = true
54
+ const { container } = render(
55
+ <Flourish
56
+ type="flourish"
57
+ id="123"
58
+ flourishType="bar"
59
+ description="foo"
60
+ layoutWidth="full-grid"
61
+ fallbackImage={anImage}
62
+ iFrame={iFrame}
63
+ />
64
+ )
65
+ expect(container).toMatchSnapshot()
66
+ })
67
+
68
+ it('renders without n-content-layout class for charts not in article body', async () => {
69
+ const inArticleBody = false
70
+ const { container } = render(
71
+ <Flourish
72
+ type="flourish"
73
+ id="123"
74
+ flourishType="bar"
75
+ description="foo"
76
+ layoutWidth="full-grid"
77
+ fallbackImage={anImage}
78
+ inArticleBody={inArticleBody}
79
+ />
80
+ )
81
+ expect(container).toMatchSnapshot()
82
+ })
83
+ })
84
+
85
+ it('sets the hideTitle param in the iframe url to true when not in article body', async () => {
86
+ const inArticleBody = false
87
+ const iFrame = true
88
+ const { container } = render(
89
+ <Flourish
90
+ type="flourish"
91
+ id="123"
92
+ flourishType="bar"
93
+ description="foo"
94
+ layoutWidth="full-grid"
95
+ fallbackImage={anImage}
96
+ iFrame={iFrame}
97
+ inArticleBody={inArticleBody}
98
+ />
99
+ )
100
+ expect(container).toMatchSnapshot()
101
+ })
102
+
103
+ it('does not set aspect ratios when in article body', async () => {
104
+ const { container } = render(
105
+ <Flourish
106
+ type="flourish"
107
+ id="123"
108
+ flourishType="bar"
109
+ description="foo"
110
+ layoutWidth="full-grid"
111
+ fallbackImage={anImage}
112
+ />
113
+ )
114
+ expect(container).toMatchSnapshot()
115
+ })
@@ -10,18 +10,31 @@ interface ContentTreeLayoutSlot extends ContentTree.Node {
10
10
  children: [ContentTree.ImageSet?, ...ContentTree.Paragraph[]]
11
11
  }
12
12
 
13
- interface ContentTreeCardLayout extends ContentTree.Node {
13
+ interface BaseLayoutProps {
14
+ layoutWidth: 'inset-left' | 'full-width' | 'full-grid'
15
+ layoutName?: string
16
+ }
17
+
18
+ interface ContentTreeCardLayout extends BaseLayoutProps, ContentTree.Node {
14
19
  type: 'layout'
15
20
  layoutName: 'auto' | 'card' | 'timeline'
16
- layoutWidth: 'inset-left' | 'full-width' | 'full-grid'
17
21
  children: ContentTreeLayoutSlot[]
18
22
  }
19
23
 
24
+ interface StaticLayout extends BaseLayoutProps {
25
+ children: ReactNode
26
+ }
27
+ /*
28
+ * @description Layout component is used to define the layout for content. It can be used with ContentTree Layout Nodes or as a static layout.
29
+ * @param layoutWidth - The width of the layout within the containing grid.
30
+ * @param layoutName - The name of the layout.
31
+ * @param children - The content to be displayed in the layout.
32
+ */
20
33
  export function Layout({
21
34
  children,
22
35
  layoutWidth,
23
- layoutName,
24
- }: React.PropsWithChildren<ContentTreeCardLayout>) {
36
+ layoutName = 'auto',
37
+ }: React.PropsWithChildren<ContentTreeCardLayout | StaticLayout>) {
25
38
  return (
26
39
  <div
27
40
  className="n-content-layout"
@@ -0,0 +1,5 @@
1
+ /* Topper styles are in o-topper codebase */
2
+ /* Flourish topper is not a distributable Origami topper, but only used via cp-pipeline-ui */
3
+ .o-topper--flourish {
4
+ padding: 0 10px;
5
+ }
@@ -8,10 +8,12 @@ import Headshot from '../Headshot'
8
8
  import Columnist from './Columnist'
9
9
  import LiveBlogIndicator from './LiveBlogIndicator'
10
10
  import { FollowButtonSlot } from './FollowButtonSlot'
11
+ import Flourish from '../Flourish'
12
+ import { Layout, LayoutContainer } from '../Layout'
11
13
  import classnames from 'classnames'
12
14
  import type { ArticleQuery } from '@financial-times/cp-content-pipeline-client'
13
15
 
14
- type TopperProps = {
16
+ export type TopperProps = {
15
17
  content: ArticleQuery['content']
16
18
  slot?: string
17
19
  followButtonSlot?: FollowButtonSlot
@@ -37,6 +39,8 @@ export default function Topper({
37
39
  const isBasic = topper.__typename === 'BasicTopper'
38
40
  const isOpinion = topper.__typename === 'OpinionTopper'
39
41
  const isPodcast = topper.__typename === 'PodcastTopper'
42
+ const isFlourish =
43
+ topper.__typename === 'TopperWithFlourish' && !!topper.leadFlourish
40
44
  const isAudio = content.__typename === 'Audio'
41
45
  const hasLayout = 'layout' in topper && topper.layout
42
46
  const hasDesign = 'design' in topper && topper.design
@@ -134,13 +138,28 @@ export default function Topper({
134
138
  undefined
135
139
  }
136
140
  />
141
+ {isLiveBlog && isFlourish ? (
142
+ <Layout layoutWidth="full-grid">
143
+ <LayoutContainer>
144
+ <Flourish
145
+ id={topper.leadFlourish.id || ''}
146
+ flourishType={topper.leadFlourish.type || ''}
147
+ description={topper.leadFlourish.description || ''}
148
+ fallbackImage={topper.leadFlourish.fallbackImage || ''}
149
+ iFrame={true}
150
+ inArticleBody={false}
151
+ />
152
+ </LayoutContainer>
153
+ </Layout>
154
+ ) : (
155
+ ''
156
+ )}
137
157
  {topper.intro && (
138
158
  <Intro
139
159
  structured={topper.intro.structured}
140
160
  source={topper.intro.source}
141
161
  />
142
162
  )}
143
-
144
163
  {hasHeadshot && !isAudio && isOpinion && topper.columnist && (
145
164
  <div className="o-topper__headshot">
146
165
  <Headshot
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+ import Topper, { TopperProps } from "../components/Topper";
3
+ import { content } from './content';
4
+ import type { ArticleQuery } from '@financial-times/cp-content-pipeline-client'
5
+
6
+ const args: TopperProps = {
7
+ content: content as unknown as ArticleQuery['content']
8
+ }
9
+
10
+ export default {
11
+ title: 'Topper',
12
+ component: Topper,
13
+ content: {}
14
+ }
15
+
16
+ export const Default = () => {
17
+ return (
18
+ <div className="story-container">
19
+ <Topper {...args} />
20
+ </div>
21
+ )
22
+ }
@@ -0,0 +1,78 @@
1
+ export const content = {
2
+ __typename: 'LiveBlogPackage',
3
+ id: 'f9d0da8a-ac43-4f0d-8af5-d597d1f13bb8',
4
+ title: 'News updates from February 2: US adds 353,000 jobs in January, US hits Iraq and Syria after drone deaths',
5
+ publishedDate: '2024-02-05T12:00:44.399Z',
6
+ firstPublishedDate: '2024-02-05T12:00:44.399Z',
7
+ standfirst: null,
8
+ topper: {
9
+ __typename: 'TopperWithFlourish',
10
+ layout: 'flourish',
11
+ layoutWidth: 'full-width',
12
+ headline: 'News updates from February 2: US adds 353,000 jobs in January, US hits Iraq and Syria after drone deaths',
13
+ backgroundColour: 'paper',
14
+ backgroundBox: null,
15
+ textShadow: null,
16
+ followButtonVariant: 'standard',
17
+ intro: {
18
+ source: 'standfirst',
19
+ structured: {
20
+ tree: {
21
+ type: 'body',
22
+ version: 1,
23
+ children: [
24
+ {
25
+ type: 'text',
26
+ value: 'Media sector scrambles to deal with fallout from phase out of cross-website trackers '
27
+ }
28
+ ]
29
+ }
30
+ }
31
+ },
32
+ displayConcept: {
33
+ id: '84cf4073-a674-4a93-aef9-dcc1832a65cb',
34
+ prefLabel: 'Amazon.com',
35
+ types: [
36
+ 'http://www.ft.com/ontology/core/Thing',
37
+ 'http://www.ft.com/ontology/concept/Concept',
38
+ 'http://www.ft.com/ontology/organisation/Organisation',
39
+ 'http://www.ft.com/ontology/company/Company',
40
+ 'http://www.ft.com/ontology/company/PublicCompany'
41
+ ],
42
+ type: 'ORGANISATION',
43
+ directType: 'http://www.ft.com/ontology/company/PublicCompany',
44
+ isPackageBrand: false,
45
+ predicate: 'http://www.ft.com/ontology/hasDisplayTag',
46
+ url: 'https://www.ft.com/stream/84cf4073-a674-4a93-aef9-dcc1832a65cb',
47
+ relativeUrl: '/stream/84cf4073-a674-4a93-aef9-dcc1832a65cb'
48
+ },
49
+ genreConcept: {
50
+ id: 'a579350c-61ce-4c00-97ca-ddaa2e0cacf6',
51
+ prefLabel: 'News',
52
+ types: [
53
+ 'http://www.ft.com/ontology/core/Thing',
54
+ 'http://www.ft.com/ontology/concept/Concept',
55
+ 'http://www.ft.com/ontology/classification/Classification',
56
+ 'http://www.ft.com/ontology/Genre'
57
+ ],
58
+ type: 'GENRE',
59
+ directType: 'http://www.ft.com/ontology/Genre',
60
+ isPackageBrand: false,
61
+ predicate: 'http://www.ft.com/ontology/classification/isClassifiedBy',
62
+ url: 'https://www.ft.com/stream/a579350c-61ce-4c00-97ca-ddaa2e0cacf6',
63
+ relativeUrl: '/stream/a579350c-61ce-4c00-97ca-ddaa2e0cacf6'
64
+ },
65
+ leadFlourish: {
66
+ type: 'visualisation',
67
+ id: '15700475',
68
+ description: 'EU Airlines',
69
+ fallbackImage: {
70
+ url: 'https://www.ft.com/__origami/service/image/v2/images/raw/https%3A%2F%2Fpublic.flourish.studio%2Fvisualisation%2F15700475%2Fthumbnail?source=cp-content-pipeline&fit=scale-down&quality=highest&width=1020&dpr=1',
71
+ type: 'visualisation',
72
+ format: 'standard',
73
+ width: 1020,
74
+ height: 892
75
+ }
76
+ }
77
+ },
78
+ }