@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
@@ -12,6 +12,8 @@ const Picture_1 = __importDefault(require("./Picture"));
12
12
  const Headshot_1 = __importDefault(require("../Headshot"));
13
13
  const Columnist_1 = __importDefault(require("./Columnist"));
14
14
  const LiveBlogIndicator_1 = __importDefault(require("./LiveBlogIndicator"));
15
+ const Flourish_1 = __importDefault(require("../Flourish"));
16
+ const Layout_1 = require("../Layout");
15
17
  const classnames_1 = __importDefault(require("classnames"));
16
18
  function Topper({ content, slot, followButtonSlot, showPremiumLabel = false, readNextSlot, }) {
17
19
  const { topper } = content;
@@ -23,6 +25,7 @@ function Topper({ content, slot, followButtonSlot, showPremiumLabel = false, rea
23
25
  const isBasic = topper.__typename === 'BasicTopper';
24
26
  const isOpinion = topper.__typename === 'OpinionTopper';
25
27
  const isPodcast = topper.__typename === 'PodcastTopper';
28
+ const isFlourish = topper.__typename === 'TopperWithFlourish' && !!topper.leadFlourish;
26
29
  const isAudio = content.__typename === 'Audio';
27
30
  const hasLayout = 'layout' in topper && topper.layout;
28
31
  const hasDesign = 'design' in topper && topper.design;
@@ -67,6 +70,9 @@ function Topper({ content, slot, followButtonSlot, showPremiumLabel = false, rea
67
70
  react_1.default.createElement(LiveBlogIndicator_1.default, { realtime: content.realtime ?? undefined, lastUpdatedDateTime: getMostRecentPostPublishedDate() }))) : (react_1.default.createElement(Tags_1.default, { __typename: topper.__typename, isPackage: isPackage, displayConcept: topper.displayConcept ?? undefined, brandConcept: ('brandConcept' in topper && topper.brandConcept) || undefined, genreConcept: ('genreConcept' in topper && topper.genreConcept) || undefined, headshot: hasHeadshot || undefined, hasColumnist: hasColumnist, followButtonVariant: topper.followButtonVariant, FollowButtonSlot: followButtonSlot })),
68
71
  react_1.default.createElement(Headline_1.default, { headline: topper.headline, showPremiumLabel: showPremiumLabel && content.accessLevel === 'premium', isLargeHeadline: ('isLargeHeadline' in topper && topper.isLargeHeadline) ??
69
72
  undefined }),
73
+ isLiveBlog && isFlourish ? (react_1.default.createElement(Layout_1.Layout, { layoutWidth: "full-grid" },
74
+ react_1.default.createElement(Layout_1.LayoutContainer, null,
75
+ react_1.default.createElement(Flourish_1.default, { id: topper.leadFlourish.id || '', flourishType: topper.leadFlourish.type || '', description: topper.leadFlourish.description || '', fallbackImage: topper.leadFlourish.fallbackImage || '', iFrame: true, inArticleBody: false })))) : (''),
70
76
  topper.intro && (react_1.default.createElement(Intro_1.default, { structured: topper.intro.structured, source: topper.intro.source })),
71
77
  hasHeadshot && !isAudio && isOpinion && topper.columnist && (react_1.default.createElement("div", { className: "o-topper__headshot" },
72
78
  react_1.default.createElement(Headshot_1.default, { headshot: topper.headshot, prefLabel: topper.columnist.prefLabel, className: 'o-topper__headshot-image', altText: headshotAltText }))),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Topper/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Topper/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import Topper from "../components/Topper";
3
+ declare const _default: {
4
+ title: string;
5
+ component: typeof Topper;
6
+ content: {};
7
+ };
8
+ export default _default;
9
+ export declare const Default: () => React.JSX.Element;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Default = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const Topper_1 = __importDefault(require("../components/Topper"));
9
+ const content_1 = require("./content");
10
+ const args = {
11
+ content: content_1.content
12
+ };
13
+ exports.default = {
14
+ title: 'Topper',
15
+ component: Topper_1.default,
16
+ content: {}
17
+ };
18
+ const Default = () => {
19
+ return (react_1.default.createElement("div", { className: "story-container" },
20
+ react_1.default.createElement(Topper_1.default, { ...args })));
21
+ };
22
+ exports.Default = Default;
23
+ //# sourceMappingURL=Topper.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Topper.stories.js","sourceRoot":"","sources":["../../src/stories/Topper.stories.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,kEAA2D;AAC3D,uCAAoC;AAGpC,MAAM,IAAI,GAAgB;IACtB,OAAO,EAAE,iBAA6C;CACzD,CAAA;AAED,kBAAe;IACX,KAAK,EAAE,QAAQ;IACf,SAAS,EAAE,gBAAM;IACjB,OAAO,EAAE,EAAE;CACd,CAAA;AAEM,MAAM,OAAO,GAAG,GAAG,EAAE;IACxB,OAAO,CACH,uCAAK,SAAS,EAAC,iBAAiB;QAC5B,8BAAC,gBAAM,OAAK,IAAI,GAAI,CAClB,CACT,CAAA;AACL,CAAC,CAAA;AANY,QAAA,OAAO,WAMnB"}
@@ -0,0 +1,65 @@
1
+ export declare const content: {
2
+ __typename: string;
3
+ id: string;
4
+ title: string;
5
+ publishedDate: string;
6
+ firstPublishedDate: string;
7
+ standfirst: null;
8
+ topper: {
9
+ __typename: string;
10
+ layout: string;
11
+ layoutWidth: string;
12
+ headline: string;
13
+ backgroundColour: string;
14
+ backgroundBox: null;
15
+ textShadow: null;
16
+ followButtonVariant: string;
17
+ intro: {
18
+ source: string;
19
+ structured: {
20
+ tree: {
21
+ type: string;
22
+ version: number;
23
+ children: {
24
+ type: string;
25
+ value: string;
26
+ }[];
27
+ };
28
+ };
29
+ };
30
+ displayConcept: {
31
+ id: string;
32
+ prefLabel: string;
33
+ types: string[];
34
+ type: string;
35
+ directType: string;
36
+ isPackageBrand: boolean;
37
+ predicate: string;
38
+ url: string;
39
+ relativeUrl: string;
40
+ };
41
+ genreConcept: {
42
+ id: string;
43
+ prefLabel: string;
44
+ types: string[];
45
+ type: string;
46
+ directType: string;
47
+ isPackageBrand: boolean;
48
+ predicate: string;
49
+ url: string;
50
+ relativeUrl: string;
51
+ };
52
+ leadFlourish: {
53
+ type: string;
54
+ id: string;
55
+ description: string;
56
+ fallbackImage: {
57
+ url: string;
58
+ type: string;
59
+ format: string;
60
+ width: number;
61
+ height: number;
62
+ };
63
+ };
64
+ };
65
+ };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.content = void 0;
4
+ exports.content = {
5
+ __typename: 'LiveBlogPackage',
6
+ id: 'f9d0da8a-ac43-4f0d-8af5-d597d1f13bb8',
7
+ title: 'News updates from February 2: US adds 353,000 jobs in January, US hits Iraq and Syria after drone deaths',
8
+ publishedDate: '2024-02-05T12:00:44.399Z',
9
+ firstPublishedDate: '2024-02-05T12:00:44.399Z',
10
+ standfirst: null,
11
+ topper: {
12
+ __typename: 'TopperWithFlourish',
13
+ layout: 'flourish',
14
+ layoutWidth: 'full-width',
15
+ headline: 'News updates from February 2: US adds 353,000 jobs in January, US hits Iraq and Syria after drone deaths',
16
+ backgroundColour: 'paper',
17
+ backgroundBox: null,
18
+ textShadow: null,
19
+ followButtonVariant: 'standard',
20
+ intro: {
21
+ source: 'standfirst',
22
+ structured: {
23
+ tree: {
24
+ type: 'body',
25
+ version: 1,
26
+ children: [
27
+ {
28
+ type: 'text',
29
+ value: 'Media sector scrambles to deal with fallout from phase out of cross-website trackers '
30
+ }
31
+ ]
32
+ }
33
+ }
34
+ },
35
+ displayConcept: {
36
+ id: '84cf4073-a674-4a93-aef9-dcc1832a65cb',
37
+ prefLabel: 'Amazon.com',
38
+ types: [
39
+ 'http://www.ft.com/ontology/core/Thing',
40
+ 'http://www.ft.com/ontology/concept/Concept',
41
+ 'http://www.ft.com/ontology/organisation/Organisation',
42
+ 'http://www.ft.com/ontology/company/Company',
43
+ 'http://www.ft.com/ontology/company/PublicCompany'
44
+ ],
45
+ type: 'ORGANISATION',
46
+ directType: 'http://www.ft.com/ontology/company/PublicCompany',
47
+ isPackageBrand: false,
48
+ predicate: 'http://www.ft.com/ontology/hasDisplayTag',
49
+ url: 'https://www.ft.com/stream/84cf4073-a674-4a93-aef9-dcc1832a65cb',
50
+ relativeUrl: '/stream/84cf4073-a674-4a93-aef9-dcc1832a65cb'
51
+ },
52
+ genreConcept: {
53
+ id: 'a579350c-61ce-4c00-97ca-ddaa2e0cacf6',
54
+ prefLabel: 'News',
55
+ types: [
56
+ 'http://www.ft.com/ontology/core/Thing',
57
+ 'http://www.ft.com/ontology/concept/Concept',
58
+ 'http://www.ft.com/ontology/classification/Classification',
59
+ 'http://www.ft.com/ontology/Genre'
60
+ ],
61
+ type: 'GENRE',
62
+ directType: 'http://www.ft.com/ontology/Genre',
63
+ isPackageBrand: false,
64
+ predicate: 'http://www.ft.com/ontology/classification/isClassifiedBy',
65
+ url: 'https://www.ft.com/stream/a579350c-61ce-4c00-97ca-ddaa2e0cacf6',
66
+ relativeUrl: '/stream/a579350c-61ce-4c00-97ca-ddaa2e0cacf6'
67
+ },
68
+ leadFlourish: {
69
+ type: 'visualisation',
70
+ id: '15700475',
71
+ description: 'EU Airlines',
72
+ fallbackImage: {
73
+ 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',
74
+ type: 'visualisation',
75
+ format: 'standard',
76
+ width: 1020,
77
+ height: 892
78
+ }
79
+ }
80
+ },
81
+ };
82
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/stories/content.tsx"],"names":[],"mappings":";;;AAAa,QAAA,OAAO,GAAG;IACnB,UAAU,EAAE,iBAAiB;IAC7B,EAAE,EAAE,sCAAsC;IAC1C,KAAK,EAAE,0GAA0G;IACjH,aAAa,EAAE,0BAA0B;IACzC,kBAAkB,EAAE,0BAA0B;IAC9C,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE;QACJ,UAAU,EAAE,oBAAoB;QAChC,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,0GAA0G;QACpH,gBAAgB,EAAE,OAAO;QACzB,aAAa,EAAE,IAAI;QACnB,UAAU,EAAE,IAAI;QAChB,mBAAmB,EAAE,UAAU;QAC/B,KAAK,EAAE;YACH,MAAM,EAAE,YAAY;YACpB,UAAU,EAAE;gBACR,IAAI,EAAE;oBACF,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,CAAC;oBACV,QAAQ,EAAE;wBACN;4BACI,IAAI,EAAE,MAAM;4BACZ,KAAK,EAAE,uFAAuF;yBACjG;qBACJ;iBACJ;aACJ;SACJ;QACD,cAAc,EAAE;YACZ,EAAE,EAAE,sCAAsC;YAC1C,SAAS,EAAE,YAAY;YACvB,KAAK,EAAE;gBACH,uCAAuC;gBACvC,4CAA4C;gBAC5C,sDAAsD;gBACtD,4CAA4C;gBAC5C,kDAAkD;aACrD;YACD,IAAI,EAAE,cAAc;YACpB,UAAU,EAAE,kDAAkD;YAC9D,cAAc,EAAE,KAAK;YACrB,SAAS,EAAE,0CAA0C;YACrD,GAAG,EAAE,gEAAgE;YACrE,WAAW,EAAE,8CAA8C;SAC9D;QACD,YAAY,EAAE;YACV,EAAE,EAAE,sCAAsC;YAC1C,SAAS,EAAE,MAAM;YACjB,KAAK,EAAE;gBACH,uCAAuC;gBACvC,4CAA4C;gBAC5C,0DAA0D;gBAC1D,kCAAkC;aACrC;YACD,IAAI,EAAE,OAAO;YACb,UAAU,EAAE,kCAAkC;YAC9C,cAAc,EAAE,KAAK;YACrB,SAAS,EAAE,0DAA0D;YACrE,GAAG,EAAE,gEAAgE;YACrE,WAAW,EAAE,8CAA8C;SAC9D;QACD,YAAY,EAAE;YACV,IAAI,EAAE,eAAe;YACrB,EAAE,EAAE,UAAU;YACd,WAAW,EAAE,aAAa;YAC1B,aAAa,EAAE;gBACb,GAAG,EAAE,iNAAiN;gBACtN,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,UAAU;gBAClB,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,GAAG;aACZ;SACF;KACN;CACJ,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cp-content-pipeline-ui",
3
- "version": "6.4.6",
3
+ "version": "6.5.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -17,9 +17,9 @@
17
17
  "@babel/preset-react": "^7.22.5",
18
18
  "@dotcom-tool-kit/npm": "^3.1.4",
19
19
  "@financial-times/content-tree": "github:financial-times/content-tree#14370e3",
20
- "@financial-times/cp-content-pipeline-client": "^3.7.0",
21
- "@financial-times/cp-content-pipeline-schema": "^2.9.2",
22
- "@financial-times/cp-content-pipeline-styles": "^2.4.1",
20
+ "@financial-times/cp-content-pipeline-client": "^3.7.1",
21
+ "@financial-times/cp-content-pipeline-schema": "^2.10.0",
22
+ "@financial-times/cp-content-pipeline-styles": "^2.4.2",
23
23
  "@financial-times/n-scrollytelling-image": "^1.1.0",
24
24
  "@financial-times/o-colors": "^6.6.2",
25
25
  "@financial-times/o-grid": "^6.1.5",
@@ -38,10 +38,11 @@
38
38
  "@storybook/react-webpack5": "^7.0.24",
39
39
  "@storybook/testing-library": "^0.2.0",
40
40
  "@sucrase/jest-plugin": "^3.0.0",
41
- "@testing-library/react": "^13.3.0",
41
+ "@testing-library/react": "^13.4.0",
42
42
  "@testing-library/user-event": "^14.4.3",
43
43
  "@types/financial-times__n-scrollytelling-image": "0.0.0",
44
44
  "@types/react": "^18.0.15",
45
+ "@types/react-test-renderer": "^18.3.0",
45
46
  "eslint-plugin-react": "^7.30.1",
46
47
  "jest-environment-jsdom": "^29.6.1",
47
48
  "n-ui-foundations": "^9.1.0",
package/src/client.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default as Clip } from './components/Clip/client/index'
2
2
  export { default as BackToTopButton } from './components/BackToTopButton/client'
3
+ export { default as FlourishSSREmbed } from './components/Flourish/client/index'
@@ -38,6 +38,7 @@ interface TrackingData {
38
38
  category: string
39
39
  contentId?: string
40
40
  action: string
41
+ url: string
41
42
  progress?: number
42
43
  amount?: number
43
44
  amountPercentage?: number
@@ -332,6 +333,7 @@ class Clip extends ClipInterface {
332
333
  //contentId: this.opts.id,
333
334
  action: eventType,
334
335
  progress: this.getRelevantProgress(),
336
+ url: window.location.href,
335
337
  video: {
336
338
  duration: this.getDuration(),
337
339
  source_url: this.opts.id,
@@ -26,13 +26,13 @@ class ProgressBar {
26
26
  private onWindowMouseMoveListener: (e: MouseEvent) => void
27
27
  private onWindowMouseUpListener: (e: MouseEvent) => void
28
28
  private opts: Required<Opts>
29
- private isMobileDevice = false
29
+
30
30
  constructor(videoEl: HTMLVideoElement, opts: Opts) {
31
31
  this.videoEl = videoEl
32
32
  this.opts = { ...defaultOpts, ...opts }
33
33
  this.onWindowMouseMoveListener = this.windowMouseMoveListener.bind(this)
34
34
  this.onWindowMouseUpListener = this.windowMouseUpListener.bind(this)
35
- this.isMobileDevice = isMobile()
35
+
36
36
  const container = document.createElement('div')
37
37
  container.classList.add('cp-clip__video-progress-bar')
38
38
  const mainBar = document.createElement('div')
@@ -88,17 +88,21 @@ class ProgressBar {
88
88
 
89
89
  //When mousedown for progressBarTimeTriggerTap time we dispatch the tap event
90
90
  container.addEventListener('mousedown', () => {
91
- this.mousePressed = true
92
- window.addEventListener('mouseup', this.onWindowMouseUpListener)
93
- window.addEventListener('mousemove', this.onWindowMouseMoveListener)
91
+ if (!isMobile()) {
92
+ this.mousePressed = true
93
+ window.addEventListener('mouseup', this.onWindowMouseUpListener)
94
+ window.addEventListener('mousemove', this.onWindowMouseMoveListener)
95
+ }
94
96
  })
95
97
 
96
98
  container.addEventListener('mouseover', () => {
97
- mainBar.classList.add('cp-clip__progress-enlarged')
99
+ if (!isMobile()) {
100
+ mainBar.classList.add('cp-clip__progress-enlarged')
101
+ }
98
102
  })
99
103
 
100
104
  container.addEventListener('mouseleave', () => {
101
- if (!this.mousePressed) {
105
+ if (!this.mousePressed && !isMobile()) {
102
106
  mainBar.classList.remove('cp-clip__progress-enlarged')
103
107
  }
104
108
  })
@@ -235,7 +239,7 @@ class ProgressBar {
235
239
  }
236
240
 
237
241
  windowMouseUpListener(e: MouseEvent) {
238
- if (this.mousePressed && !this.isMobileDevice) {
242
+ if (this.mousePressed) {
239
243
  this.scrub(e.clientX)
240
244
  this.mousePressed = false
241
245
  if (!e.target || !this?.container?.contains(e.target as Node)) {
@@ -1,6 +1,8 @@
1
1
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
2
  // @ts-nocheck
3
3
  import React from 'react'
4
+ // TODO: React test renderer is depracated, we should use @testing-library/react
5
+ // https://react.dev/warnings/react-test-renderer
4
6
  import renderer from 'react-test-renderer'
5
7
  import prettier from 'prettier'
6
8
  import { TextEncoder } from 'util'
@@ -0,0 +1,17 @@
1
+ function hideIFrame(): void {
2
+ const flourishComponent = document.querySelectorAll(
3
+ '[data-component="flourish"]'
4
+ )
5
+ flourishComponent.forEach((component) => {
6
+ component.classList.add('disable-iframe')
7
+ })
8
+ }
9
+
10
+ function init(featureFlag: boolean = true): void {
11
+ // turning the feature flag off will hide the iframe and display the fallback image
12
+ if (!featureFlag) {
13
+ hideIFrame()
14
+ }
15
+ }
16
+
17
+ export default init
@@ -0,0 +1,38 @@
1
+ .flourish {
2
+ &.flourish--iFrame {
3
+ @include oGridRespondTo(XL) {
4
+ max-width: oGridColspan(12);
5
+ }
6
+ margin-bottom: 0;
7
+ margin-top: oSpacingByName("s4")
8
+ }
9
+ // We need to force the iframe to be hidden if we turn the feature flag off
10
+ &.disable-iframe {
11
+ .flourish__i-frame {
12
+ display: none;
13
+ }
14
+
15
+ .flourish__figure {
16
+ display: block;
17
+ }
18
+ }
19
+ }
20
+ // Without JS the i-frame will not work, so we hide it
21
+ .no-js {
22
+ .flourish__i-frame {
23
+ display: none;
24
+ }
25
+ }
26
+ .js {
27
+ .flourish__i-frame {
28
+ display: block;
29
+ border: 0;
30
+ @media screen and (max-width: 739px) {
31
+ // We need to enforce this otherwise it will use the inline styling
32
+ aspect-ratio: 3/4 !important;
33
+ }
34
+ }
35
+ .flourish__figure {
36
+ display: none;
37
+ }
38
+ }
@@ -1,12 +1,25 @@
1
1
  import React from 'react'
2
2
  import classnames from 'classnames'
3
- import { ContentTree } from '@financial-times/content-tree'
4
- import { FlourishFragment } from '@financial-times/cp-content-pipeline-client'
5
3
 
6
4
  type disclaimerProps = {
7
5
  id: string
8
6
  }
9
7
 
8
+ type FlourishProps = {
9
+ id: string
10
+ type?: string
11
+ flourishType?: string
12
+ description?: string
13
+ layoutWidth?: string
14
+ fallbackImage: {
15
+ url?: string | null | undefined
16
+ width?: number | null | undefined
17
+ height?: number | null | undefined
18
+ }
19
+ iFrame?: boolean
20
+ inArticleBody?: boolean
21
+ }
22
+
10
23
  const DisclaimerNotice = ({ id }: disclaimerProps) => (
11
24
  <div
12
25
  id={id}
@@ -30,20 +43,50 @@ export default function Flourish({
30
43
  description,
31
44
  layoutWidth,
32
45
  fallbackImage,
33
- }: ContentTree.Flourish & FlourishFragment) {
46
+ iFrame = false,
47
+ inArticleBody = true,
48
+ }: FlourishProps) {
34
49
  const anchorHref = `#${id}`
35
50
  const fullGrid = layoutWidth === 'full-grid' || layoutWidth === 'grid'
36
51
  const figureClassnames = classnames({
37
52
  'n-content-picture': true,
38
53
  'n-content-layout__container': true,
39
54
  'n-content-picture--wide': fullGrid,
55
+ flourish__figure: iFrame,
40
56
  })
41
57
 
58
+ const iframeAspectRatio =
59
+ iFrame && fallbackImage?.width && fallbackImage?.height
60
+ ? `${fallbackImage.width}/${fallbackImage.height}`
61
+ : '16/9'
62
+
63
+ const imageAspectRatio =
64
+ !inArticleBody && fallbackImage?.width && fallbackImage?.height
65
+ ? {
66
+ width: '100%',
67
+ aspectRatio: `${fallbackImage.width}/${fallbackImage.height}`,
68
+ }
69
+ : {}
70
+
71
+ if (!id) return null
72
+
42
73
  return (
43
74
  <div
44
- className="n-content-layout"
75
+ className={classnames({
76
+ 'n-content-layout': inArticleBody,
77
+ flourish: iFrame,
78
+ 'flourish--iFrame': iFrame,
79
+ })}
45
80
  data-layout-width={fullGrid ? 'full-grid' : null}
81
+ data-component="flourish"
46
82
  >
83
+ {iFrame && (
84
+ <iframe
85
+ src={`https://flo.uri.sh/visualisation/${id}/embed?hideTitle=${!inArticleBody}`} // hide the title of if in topper
86
+ style={{ width: '100%', aspectRatio: iframeAspectRatio }}
87
+ className="flourish__i-frame"
88
+ ></iframe>
89
+ )}
47
90
  <figure
48
91
  className={figureClassnames}
49
92
  data-original-image-width={fullGrid ? fallbackImage?.width : null}
@@ -51,12 +94,18 @@ export default function Flourish({
51
94
  >
52
95
  <a href={anchorHref}>
53
96
  <picture
54
- data-asset-type="flourish"
97
+ // `flourish-embed` loads an iframe containing the JS version of a flourish chart
98
+ // `flourish` will be instead targeted by the flourish JS, that will replace the picture with the flourish JS version contained in an iframe
99
+ data-asset-type={iFrame ? 'flourish-embed' : 'flourish'}
55
100
  data-flourish-id={id}
56
101
  data-flourish-type={flourishType}
57
102
  >
58
103
  <DisclaimerNotice id={id} />
59
- <img src={fallbackImage?.url} alt={description} />
104
+ <img
105
+ src={fallbackImage?.url || ''}
106
+ alt={description}
107
+ style={imageAspectRatio}
108
+ />
60
109
  </picture>
61
110
  </a>
62
111
  </figure>