@financial-times/cp-content-pipeline-ui 7.0.2 → 7.1.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.
- package/CHANGELOG.md +13 -0
- package/lib/client.d.ts +1 -0
- package/lib/client.js +3 -1
- package/lib/client.js.map +1 -1
- package/lib/components/Body/index.test.js +12 -11
- package/lib/components/Body/index.test.js.map +1 -1
- package/lib/components/CustomCodeComponent/client/index.d.ts +15 -0
- package/lib/components/CustomCodeComponent/client/index.js +95 -0
- package/lib/components/CustomCodeComponent/client/index.js.map +1 -0
- package/lib/components/CustomCodeComponent/index.d.ts +19 -0
- package/lib/components/CustomCodeComponent/index.js +17 -0
- package/lib/components/CustomCodeComponent/index.js.map +1 -0
- package/lib/components/Flourish/index.js +2 -5
- package/lib/components/Flourish/index.js.map +1 -1
- package/lib/components/Layout/index.d.ts +1 -1
- package/lib/components/Message/index.d.ts +9 -0
- package/lib/components/Message/index.js +18 -0
- package/lib/components/Message/index.js.map +1 -0
- package/lib/components/Message/test/snapshot.spec.d.ts +1 -0
- package/lib/components/Message/test/snapshot.spec.js +23 -0
- package/lib/components/Message/test/snapshot.spec.js.map +1 -0
- package/lib/components/PartnerContentHeader/index.js +2 -3
- package/lib/components/PartnerContentHeader/index.js.map +1 -1
- package/lib/components/RichText/BasicComponents.d.ts +1 -0
- package/lib/components/RichText/BasicComponents.js +3 -1
- package/lib/components/RichText/BasicComponents.js.map +1 -1
- package/lib/components/RichText/index.js +3 -0
- package/lib/components/RichText/index.js.map +1 -1
- package/lib/components/Workarounds.d.ts +5 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/stories/Message.stories.d.ts +11 -0
- package/lib/stories/Message.stories.js +30 -0
- package/lib/stories/Message.stories.js.map +1 -0
- package/package.json +3 -2
- package/src/client.ts +1 -0
- package/src/components/Body/index.test.tsx +23 -24
- package/src/components/CustomCodeComponent/client/index.ts +121 -0
- package/src/components/CustomCodeComponent/index.tsx +54 -0
- package/src/components/Flourish/index.tsx +5 -26
- package/src/components/Flourish/test/__snapshots__/snapshot.spec.tsx.snap +12 -12
- package/src/components/Layout/index.tsx +1 -1
- package/src/components/Message/index.tsx +35 -0
- package/src/components/Message/test/__snapshots__/snapshot.spec.tsx.snap +45 -0
- package/src/components/Message/test/snapshot.spec.tsx +31 -0
- package/src/components/PartnerContentHeader/index.tsx +6 -8
- package/src/components/RichText/BasicComponents.tsx +4 -0
- package/src/components/RichText/index.tsx +4 -0
- package/src/components/Workarounds.ts +12 -0
- package/src/index.ts +2 -0
- package/src/stories/Message.stories.scss +5 -0
- package/src/stories/Message.stories.tsx +29 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
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.noticeInformCustomText = exports.noticeInformDefault = void 0;
|
|
7
|
+
const Message_1 = __importDefault(require("../components/Message"));
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
9
|
+
require("./Message.stories.scss");
|
|
10
|
+
exports.default = {
|
|
11
|
+
title: 'Message',
|
|
12
|
+
component: Message_1.default,
|
|
13
|
+
content: {},
|
|
14
|
+
};
|
|
15
|
+
const noticeInformArgs = {
|
|
16
|
+
id: '',
|
|
17
|
+
type: 'notice',
|
|
18
|
+
state: 'inform',
|
|
19
|
+
};
|
|
20
|
+
const noticeInformDefault = () => react_1.default.createElement(Message_1.default, { ...noticeInformArgs });
|
|
21
|
+
exports.noticeInformDefault = noticeInformDefault;
|
|
22
|
+
const noticeInformCustomTextArgs = {
|
|
23
|
+
id: '',
|
|
24
|
+
type: 'notice',
|
|
25
|
+
state: 'inform',
|
|
26
|
+
text: 'This is a custom message',
|
|
27
|
+
};
|
|
28
|
+
const noticeInformCustomText = () => (react_1.default.createElement(Message_1.default, { ...noticeInformCustomTextArgs }));
|
|
29
|
+
exports.noticeInformCustomText = noticeInformCustomText;
|
|
30
|
+
//# sourceMappingURL=Message.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Message.stories.js","sourceRoot":"","sources":["../../src/stories/Message.stories.tsx"],"names":[],"mappings":";;;;;;AAAA,oEAA2C;AAE3C,kDAAyB;AACzB,kCAA+B;AAE/B,kBAAe;IACb,KAAK,EAAE,SAAS;IAChB,SAAS,EAAE,iBAAO;IAClB,OAAO,EAAE,EAAE;CACZ,CAAA;AAED,MAAM,gBAAgB,GAAiB;IACrC,EAAE,EAAE,EAAE;IACN,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;CAChB,CAAA;AAEM,MAAM,mBAAmB,GAAG,GAAG,EAAE,CAAC,8BAAC,iBAAO,OAAK,gBAAgB,GAAI,CAAA;AAA7D,QAAA,mBAAmB,uBAA0C;AAE1E,MAAM,0BAA0B,GAAiB;IAC/C,EAAE,EAAE,EAAE;IACN,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,0BAA0B;CACjC,CAAA;AAEM,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC,CAC1C,8BAAC,iBAAO,OAAK,0BAA0B,GAAI,CAC5C,CAAA;AAFY,QAAA,sBAAsB,0BAElC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/cp-content-pipeline-ui",
|
|
3
|
-
"version": "7.0
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
"@babel/preset-env": "^7.22.5",
|
|
17
17
|
"@babel/preset-react": "^7.22.5",
|
|
18
18
|
"@dotcom-tool-kit/npm": "^3.3.2",
|
|
19
|
-
"@financial-times/content-tree": "github:financial-times/content-tree#
|
|
19
|
+
"@financial-times/content-tree": "github:financial-times/content-tree#056af70",
|
|
20
20
|
"@financial-times/n-scrollytelling-image": "^1.1.0",
|
|
21
21
|
"@financial-times/o-colors": "^6.6.2",
|
|
22
22
|
"@financial-times/o-grid": "^6.1.5",
|
|
23
23
|
"@financial-times/o-icons": "^7.7.0",
|
|
24
|
+
"@financial-times/o-message": "^5.4.4",
|
|
24
25
|
"@financial-times/o-share": "^10.0.1",
|
|
25
26
|
"@financial-times/o-spacing": "^3.2.3",
|
|
26
27
|
"@financial-times/o-tracking": "^4.5.0",
|
package/src/client.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { default as Clip } from './components/Clip/client/index'
|
|
|
2
2
|
export { default as BackToTopButton } from './components/BackToTopButton/client'
|
|
3
3
|
export { default as FlourishSSREmbed } from './components/Flourish/client/index'
|
|
4
4
|
export { TopperTracker } from './components/Topper/client/index'
|
|
5
|
+
export { default as CustomCodeComponentClient } from './components/CustomCodeComponent/client/index'
|
|
@@ -36,12 +36,17 @@ const baseContent: ArticleQuery['content'] = {
|
|
|
36
36
|
},
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
// these are the only content types we currently care about rendering bodies for
|
|
40
|
+
const typesToTest = [
|
|
41
|
+
'Article',
|
|
42
|
+
'Video',
|
|
43
|
+
'Audio',
|
|
44
|
+
'LiveBlogPackage',
|
|
45
|
+
'ContentPackage',
|
|
46
|
+
] satisfies ArticleQuery['content']['__typename'][]
|
|
47
|
+
|
|
48
|
+
const extraContentForType = {
|
|
49
|
+
Article: {},
|
|
45
50
|
Audio: {
|
|
46
51
|
__typename: 'Audio',
|
|
47
52
|
media: [
|
|
@@ -83,7 +88,10 @@ const extraContentForType: Partial<
|
|
|
83
88
|
Video: {
|
|
84
89
|
__typename: 'Video',
|
|
85
90
|
},
|
|
86
|
-
}
|
|
91
|
+
} satisfies Record<
|
|
92
|
+
(typeof typesToTest)[number],
|
|
93
|
+
Partial<ArticleQuery['content']>
|
|
94
|
+
>
|
|
87
95
|
|
|
88
96
|
const extraPropsForType: Partial<
|
|
89
97
|
Record<ArticleQuery['content']['__typename'], Record<string, unknown>>
|
|
@@ -95,24 +103,15 @@ const extraPropsForType: Partial<
|
|
|
95
103
|
},
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
|
|
99
|
-
const typesToTest: ArticleQuery['content']['__typename'][] = [
|
|
100
|
-
'Article',
|
|
101
|
-
'Video',
|
|
102
|
-
'Audio',
|
|
103
|
-
'LiveBlogPackage',
|
|
104
|
-
'ContentPackage',
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
const legacyOverridesToTest: [
|
|
108
|
-
ArticleQuery['content']['__typename'],
|
|
109
|
-
keyof BodyComponentMapRecord
|
|
110
|
-
][] = [
|
|
106
|
+
const legacyOverridesToTest = [
|
|
111
107
|
['Article', 'article-body'],
|
|
112
108
|
['LiveBlogPackage', 'live-blog-body'],
|
|
113
109
|
['ContentPackage', 'content-package-body'],
|
|
114
110
|
['Audio', 'podcast-body'],
|
|
115
|
-
]
|
|
111
|
+
] satisfies [
|
|
112
|
+
ArticleQuery['content']['__typename'],
|
|
113
|
+
keyof BodyComponentMapRecord
|
|
114
|
+
][]
|
|
116
115
|
|
|
117
116
|
describe('Body', () => {
|
|
118
117
|
let mockDate: jest.SpyInstance
|
|
@@ -128,7 +127,7 @@ describe('Body', () => {
|
|
|
128
127
|
test.each(typesToTest)('renders default renderer for %s', (type) => {
|
|
129
128
|
const { asFragment } = render(
|
|
130
129
|
<Body
|
|
131
|
-
content={{ ...baseContent, ...
|
|
130
|
+
content={{ ...baseContent, ...extraContentForType[type] }}
|
|
132
131
|
{...(extraPropsForType[type] ?? {})}
|
|
133
132
|
/>
|
|
134
133
|
)
|
|
@@ -143,7 +142,7 @@ describe('Body', () => {
|
|
|
143
142
|
(type, overrideName) => {
|
|
144
143
|
const { asFragment } = render(
|
|
145
144
|
<Body
|
|
146
|
-
content={{ ...baseContent, ...
|
|
145
|
+
content={{ ...baseContent, ...extraContentForType[type] }}
|
|
147
146
|
{...(extraPropsForType[type] ?? {})}
|
|
148
147
|
bodyComponents={{
|
|
149
148
|
[overrideName]: ({
|
|
@@ -164,7 +163,7 @@ describe('Body', () => {
|
|
|
164
163
|
test.each(typesToTest)('renders override renderer for %s', (type) => {
|
|
165
164
|
const { asFragment } = render(
|
|
166
165
|
<Body
|
|
167
|
-
content={{ ...baseContent, ...
|
|
166
|
+
content={{ ...baseContent, ...extraContentForType[type] }}
|
|
168
167
|
{...(extraPropsForType[type] ?? {})}
|
|
169
168
|
bodyComponents={{
|
|
170
169
|
[type]: ({ content }: { content: ArticleQuery['content'] }) => (
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
type Component = {
|
|
2
|
+
id: string
|
|
3
|
+
name: string
|
|
4
|
+
type: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type TrackingData = {
|
|
8
|
+
component: Component
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* TrackMount
|
|
13
|
+
* @description Track initial render of a custom code component
|
|
14
|
+
* @param {HTMLElement} mountElement - The custom code component
|
|
15
|
+
* @param {TrackingData} trackingData - The specific component data
|
|
16
|
+
*/
|
|
17
|
+
class TrackMount {
|
|
18
|
+
constructor(
|
|
19
|
+
private mountElement: Element,
|
|
20
|
+
private trackingData: TrackingData
|
|
21
|
+
) {
|
|
22
|
+
this.init()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private init() {
|
|
26
|
+
this.mountElement.addEventListener('ccc-connected', () => {
|
|
27
|
+
new TrackView(this.mountElement as Element, this.trackingData)
|
|
28
|
+
this.handleMount()
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private handleMount = () => {
|
|
33
|
+
const event = new CustomEvent('oTracking.event', {
|
|
34
|
+
detail: {
|
|
35
|
+
category: 'component',
|
|
36
|
+
action: 'mount',
|
|
37
|
+
...this.trackingData,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
document.body.dispatchEvent(event)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* TrackView
|
|
46
|
+
* @description Track the view of a rendered custom code component
|
|
47
|
+
* @param {HTMLElement} mountElement - The custom code component
|
|
48
|
+
* @param {TrackingData} trackingData - The specific component data
|
|
49
|
+
*/
|
|
50
|
+
class TrackView {
|
|
51
|
+
private observer: IntersectionObserver | undefined
|
|
52
|
+
constructor(
|
|
53
|
+
private viewElement: Element,
|
|
54
|
+
private trackingData: TrackingData
|
|
55
|
+
) {
|
|
56
|
+
this.viewElement = viewElement as Element
|
|
57
|
+
this.trackingData = trackingData
|
|
58
|
+
this.init()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private init() {
|
|
62
|
+
//Intersection observer that observes when viewElement is in view
|
|
63
|
+
this.observer = new IntersectionObserver((entries) => {
|
|
64
|
+
entries.forEach((entry) => {
|
|
65
|
+
if (entry.isIntersecting) {
|
|
66
|
+
this.handleView()
|
|
67
|
+
this.observer?.disconnect()
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
this.observer.observe(this.viewElement as Element)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private handleView = () => {
|
|
75
|
+
const event = new CustomEvent('oTracking.event', {
|
|
76
|
+
detail: {
|
|
77
|
+
category: 'component',
|
|
78
|
+
action: 'view',
|
|
79
|
+
...this.trackingData,
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
document.body.dispatchEvent(event)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
destroy(): void {
|
|
86
|
+
this.observer?.disconnect()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* CustomCodeComponentClient
|
|
92
|
+
* @description Track the view of a rendered custom code component
|
|
93
|
+
* @param {HTMLElement} el - The custom code component
|
|
94
|
+
* @param {TrackingData} trackingData - The tracking data
|
|
95
|
+
*/
|
|
96
|
+
class CustomCodeComponentClient {
|
|
97
|
+
/**
|
|
98
|
+
* Track the mount of a custom code component
|
|
99
|
+
*/
|
|
100
|
+
private trackingMount: TrackMount
|
|
101
|
+
|
|
102
|
+
constructor(el: Element) {
|
|
103
|
+
const trackingData = {
|
|
104
|
+
component: {
|
|
105
|
+
id: el.getAttribute('id') ?? '',
|
|
106
|
+
name: el.getAttribute('path') ?? '',
|
|
107
|
+
type: 'custom-code-component',
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
this.trackingMount = new TrackMount(el as Element, trackingData)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static init(rootEl?: Element): (CustomCodeComponentClient | undefined)[] {
|
|
114
|
+
const root = rootEl instanceof Element ? rootEl : document
|
|
115
|
+
return Array.from(root.querySelectorAll('custom-code-component')).map(
|
|
116
|
+
(el: Element) => new CustomCodeComponentClient(el)
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export default CustomCodeComponentClient
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import Message from '../Message'
|
|
3
|
+
import { Layout } from '../Layout'
|
|
4
|
+
import RichText from '../RichText'
|
|
5
|
+
import { ContentProps } from '../types'
|
|
6
|
+
import * as ComponentWorkarounds from '../Workarounds'
|
|
7
|
+
|
|
8
|
+
interface CustomCodeComponentProps
|
|
9
|
+
extends ContentProps<ComponentWorkarounds.CustomCodeComponent> {}
|
|
10
|
+
|
|
11
|
+
declare module 'react' {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
13
|
+
namespace JSX {
|
|
14
|
+
interface IntrinsicElements {
|
|
15
|
+
'custom-code-component': {
|
|
16
|
+
path: string
|
|
17
|
+
version: string
|
|
18
|
+
id: string
|
|
19
|
+
children: React.ReactNode
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const CustomCodeComponent: React.FC<
|
|
26
|
+
React.PropsWithChildren<CustomCodeComponentProps>
|
|
27
|
+
> = ({
|
|
28
|
+
content: {
|
|
29
|
+
path,
|
|
30
|
+
versionRange,
|
|
31
|
+
id,
|
|
32
|
+
layoutWidth = 'in-line',
|
|
33
|
+
attributes = {},
|
|
34
|
+
body,
|
|
35
|
+
},
|
|
36
|
+
}: CustomCodeComponentProps) => {
|
|
37
|
+
return (
|
|
38
|
+
<Layout
|
|
39
|
+
content={{ type: 'layout', layoutName: 'auto', layoutWidth: layoutWidth }}
|
|
40
|
+
>
|
|
41
|
+
<custom-code-component
|
|
42
|
+
path={path}
|
|
43
|
+
version={versionRange}
|
|
44
|
+
{...attributes}
|
|
45
|
+
id={id}
|
|
46
|
+
>
|
|
47
|
+
<Message id={id} type="notice" state="inform" />
|
|
48
|
+
{body?.structured && <RichText structuredContent={body.structured} />}
|
|
49
|
+
</custom-code-component>
|
|
50
|
+
</Layout>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default CustomCodeComponent
|
|
@@ -2,36 +2,15 @@ import React from 'react'
|
|
|
2
2
|
import classnames from 'classnames'
|
|
3
3
|
import { ContentProps } from '../types'
|
|
4
4
|
import { ContentTreeWorkarounds } from '@financial-times/cp-content-pipeline-schema'
|
|
5
|
-
|
|
6
|
-
interface disclaimerProps {
|
|
7
|
-
id: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const DisclaimerNotice = ({ id }: disclaimerProps) => (
|
|
11
|
-
<div
|
|
12
|
-
id={id}
|
|
13
|
-
className="flourish-disclaimer o-message o-message--alert o-message--neutral"
|
|
14
|
-
data-o-component="o-message"
|
|
15
|
-
>
|
|
16
|
-
<div className="o-message__container">
|
|
17
|
-
<div className="o-message__content">
|
|
18
|
-
<p className="o-message__content-main">
|
|
19
|
-
You are seeing a snapshot of an interactive graphic. This is most
|
|
20
|
-
likely due to being offline or JavaScript being disabled in your
|
|
21
|
-
browser.
|
|
22
|
-
</p>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
)
|
|
5
|
+
import Message from '../Message'
|
|
27
6
|
|
|
28
7
|
interface FlourishProps extends ContentProps<ContentTreeWorkarounds.Flourish> {
|
|
29
|
-
|
|
30
|
-
|
|
8
|
+
iFrame?: boolean
|
|
9
|
+
inArticleBody?: boolean
|
|
31
10
|
}
|
|
32
11
|
|
|
33
12
|
const Flourish: React.FC<FlourishProps> = ({
|
|
34
|
-
|
|
13
|
+
content: { id, flourishType, description, layoutWidth, fallbackImage },
|
|
35
14
|
iFrame = false,
|
|
36
15
|
inArticleBody = true,
|
|
37
16
|
}) => {
|
|
@@ -92,7 +71,7 @@ const Flourish: React.FC<FlourishProps> = ({
|
|
|
92
71
|
data-flourish-id={id}
|
|
93
72
|
data-flourish-type={flourishType}
|
|
94
73
|
>
|
|
95
|
-
<
|
|
74
|
+
<Message id={id} type="notice" state="inform" />
|
|
96
75
|
<img
|
|
97
76
|
src={fallbackImage?.url || ''}
|
|
98
77
|
alt={description}
|
|
@@ -20,7 +20,7 @@ exports[`Flourish component renders ignoring layout different from full-grid 1`]
|
|
|
20
20
|
data-flourish-type="bar"
|
|
21
21
|
>
|
|
22
22
|
<div
|
|
23
|
-
class="
|
|
23
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
24
24
|
data-o-component="o-message"
|
|
25
25
|
id="123"
|
|
26
26
|
>
|
|
@@ -33,7 +33,7 @@ exports[`Flourish component renders ignoring layout different from full-grid 1`]
|
|
|
33
33
|
<p
|
|
34
34
|
class="o-message__content-main"
|
|
35
35
|
>
|
|
36
|
-
|
|
36
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
37
37
|
</p>
|
|
38
38
|
</div>
|
|
39
39
|
</div>
|
|
@@ -72,7 +72,7 @@ exports[`Flourish component renders with a full-grid layout and fallback image 1
|
|
|
72
72
|
data-flourish-type="bar"
|
|
73
73
|
>
|
|
74
74
|
<div
|
|
75
|
-
class="
|
|
75
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
76
76
|
data-o-component="o-message"
|
|
77
77
|
id="123"
|
|
78
78
|
>
|
|
@@ -85,7 +85,7 @@ exports[`Flourish component renders with a full-grid layout and fallback image 1
|
|
|
85
85
|
<p
|
|
86
86
|
class="o-message__content-main"
|
|
87
87
|
>
|
|
88
|
-
|
|
88
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
89
89
|
</p>
|
|
90
90
|
</div>
|
|
91
91
|
</div>
|
|
@@ -129,7 +129,7 @@ exports[`Flourish component renders with an iframe rather than using the embed s
|
|
|
129
129
|
data-flourish-type="bar"
|
|
130
130
|
>
|
|
131
131
|
<div
|
|
132
|
-
class="
|
|
132
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
133
133
|
data-o-component="o-message"
|
|
134
134
|
id="123"
|
|
135
135
|
>
|
|
@@ -142,7 +142,7 @@ exports[`Flourish component renders with an iframe rather than using the embed s
|
|
|
142
142
|
<p
|
|
143
143
|
class="o-message__content-main"
|
|
144
144
|
>
|
|
145
|
-
|
|
145
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
146
146
|
</p>
|
|
147
147
|
</div>
|
|
148
148
|
</div>
|
|
@@ -181,7 +181,7 @@ exports[`Flourish component renders without n-content-layout class for charts no
|
|
|
181
181
|
data-flourish-type="bar"
|
|
182
182
|
>
|
|
183
183
|
<div
|
|
184
|
-
class="
|
|
184
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
185
185
|
data-o-component="o-message"
|
|
186
186
|
id="123"
|
|
187
187
|
>
|
|
@@ -194,7 +194,7 @@ exports[`Flourish component renders without n-content-layout class for charts no
|
|
|
194
194
|
<p
|
|
195
195
|
class="o-message__content-main"
|
|
196
196
|
>
|
|
197
|
-
|
|
197
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
198
198
|
</p>
|
|
199
199
|
</div>
|
|
200
200
|
</div>
|
|
@@ -234,7 +234,7 @@ exports[`does not set aspect ratios when in article body 1`] = `
|
|
|
234
234
|
data-flourish-type="bar"
|
|
235
235
|
>
|
|
236
236
|
<div
|
|
237
|
-
class="
|
|
237
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
238
238
|
data-o-component="o-message"
|
|
239
239
|
id="123"
|
|
240
240
|
>
|
|
@@ -247,7 +247,7 @@ exports[`does not set aspect ratios when in article body 1`] = `
|
|
|
247
247
|
<p
|
|
248
248
|
class="o-message__content-main"
|
|
249
249
|
>
|
|
250
|
-
|
|
250
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
251
251
|
</p>
|
|
252
252
|
</div>
|
|
253
253
|
</div>
|
|
@@ -291,7 +291,7 @@ exports[`sets the hideTitle param in the iframe url to true when not in article
|
|
|
291
291
|
data-flourish-type="bar"
|
|
292
292
|
>
|
|
293
293
|
<div
|
|
294
|
-
class="
|
|
294
|
+
class="cp-message o-message o-message--inform o-message--notice"
|
|
295
295
|
data-o-component="o-message"
|
|
296
296
|
id="123"
|
|
297
297
|
>
|
|
@@ -304,7 +304,7 @@ exports[`sets the hideTitle param in the iframe url to true when not in article
|
|
|
304
304
|
<p
|
|
305
305
|
class="o-message__content-main"
|
|
306
306
|
>
|
|
307
|
-
|
|
307
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
308
308
|
</p>
|
|
309
309
|
</div>
|
|
310
310
|
</div>
|
|
@@ -2,7 +2,7 @@ import { ContentTree } from '@financial-times/content-tree'
|
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { ContentProps } from '../types'
|
|
4
4
|
|
|
5
|
-
interface LayoutProps extends ContentProps<ContentTree.transit.Layout
|
|
5
|
+
interface LayoutProps extends ContentProps<Omit<ContentTree.transit.Layout, 'children'>> {}
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* @description Layout component is used to define the layout for content. It can be used with ContentTree Layout Nodes or as a static layout.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import classnames from 'classnames'
|
|
3
|
+
|
|
4
|
+
export type MessageProps = {
|
|
5
|
+
id: string
|
|
6
|
+
type?: string
|
|
7
|
+
state?: string
|
|
8
|
+
text?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Message: React.FC<MessageProps> = ({
|
|
12
|
+
id,
|
|
13
|
+
type,
|
|
14
|
+
state,
|
|
15
|
+
text = 'Some content could not load. Check your internet connection or browser settings.',
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
id={id}
|
|
20
|
+
className={classnames('cp-message', 'o-message', {
|
|
21
|
+
[`o-message--${state}`]: state,
|
|
22
|
+
[`o-message--${type}`]: type,
|
|
23
|
+
})}
|
|
24
|
+
data-o-component="o-message"
|
|
25
|
+
>
|
|
26
|
+
<div className="o-message__container">
|
|
27
|
+
<div className="o-message__content">
|
|
28
|
+
<p className="o-message__content-main">{text}</p>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default Message
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Message component renders default 1`] = `
|
|
4
|
+
<div
|
|
5
|
+
className="cp-message o-message o-message--neutral o-message--alert"
|
|
6
|
+
data-o-component="o-message"
|
|
7
|
+
id="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
|
8
|
+
>
|
|
9
|
+
<div
|
|
10
|
+
className="o-message__container"
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
className="o-message__content"
|
|
14
|
+
>
|
|
15
|
+
<p
|
|
16
|
+
className="o-message__content-main"
|
|
17
|
+
>
|
|
18
|
+
Some content could not load. Check your internet connection or browser settings.
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
exports[`Message component renders with custom text 1`] = `
|
|
26
|
+
<div
|
|
27
|
+
className="cp-message o-message o-message--neutral o-message--alert"
|
|
28
|
+
data-o-component="o-message"
|
|
29
|
+
id="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
|
30
|
+
>
|
|
31
|
+
<div
|
|
32
|
+
className="o-message__container"
|
|
33
|
+
>
|
|
34
|
+
<div
|
|
35
|
+
className="o-message__content"
|
|
36
|
+
>
|
|
37
|
+
<p
|
|
38
|
+
className="o-message__content-main"
|
|
39
|
+
>
|
|
40
|
+
This is a custom message
|
|
41
|
+
</p>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
`;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import renderer from 'react-test-renderer'
|
|
3
|
+
import Message from '../index'
|
|
4
|
+
|
|
5
|
+
describe('Message component', () => {
|
|
6
|
+
it('renders default', () => {
|
|
7
|
+
const tree = renderer
|
|
8
|
+
.create(
|
|
9
|
+
<Message
|
|
10
|
+
id={'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}
|
|
11
|
+
type="alert"
|
|
12
|
+
state="neutral"
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
15
|
+
.toJSON()
|
|
16
|
+
expect(tree).toMatchSnapshot()
|
|
17
|
+
})
|
|
18
|
+
it('renders with custom text', () => {
|
|
19
|
+
const tree = renderer
|
|
20
|
+
.create(
|
|
21
|
+
<Message
|
|
22
|
+
id={'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'}
|
|
23
|
+
type="alert"
|
|
24
|
+
state="neutral"
|
|
25
|
+
text="This is a custom message"
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
.toJSON()
|
|
29
|
+
expect(tree).toMatchSnapshot()
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -3,18 +3,16 @@ import { TooltipToggle } from '@financial-times/o3-tooltip'
|
|
|
3
3
|
|
|
4
4
|
const PartnerContentHeader = ({ name = 'Partner' }: { name: string }) => {
|
|
5
5
|
return (
|
|
6
|
-
<div className="partner-content-header">
|
|
6
|
+
<div className="partner-content-header" data-o3-brand="core">
|
|
7
7
|
<div className="partner-content-header__content">
|
|
8
8
|
<div className="partner-content-header__client">{name}</div>
|
|
9
9
|
<div className="partner-content-header__title">
|
|
10
10
|
<p>Partner Content</p>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/>
|
|
17
|
-
</div>
|
|
11
|
+
<TooltipToggle
|
|
12
|
+
placement="bottom"
|
|
13
|
+
content={`This content was paid for by ${name} and produced in partnership with the Financial Times Commercial department`}
|
|
14
|
+
infoLabel="More information on Partner Content"
|
|
15
|
+
/>
|
|
18
16
|
</div>
|
|
19
17
|
</div>
|
|
20
18
|
</div>
|
|
@@ -50,6 +50,10 @@ export const Strikethrough: React.FC<
|
|
|
50
50
|
React.PropsWithChildren<ContentProps<ContentTree.Strikethrough>>
|
|
51
51
|
> = (props) => <s>{props.children}</s>
|
|
52
52
|
|
|
53
|
+
export const CccFallbackText: React.FC<
|
|
54
|
+
React.PropsWithChildren<ContentProps<ContentTreeWorkarounds.CccFallbackText>>
|
|
55
|
+
> = (props) => <div>{props.children}</div>
|
|
56
|
+
|
|
53
57
|
export const TableRow: React.FC<
|
|
54
58
|
React.PropsWithChildren<ContentProps<ContentTreeWorkarounds.TableRow>>
|
|
55
59
|
> = (props) => <tr>{props.children}</tr>
|