@financial-times/x-teaser 8.1.0 → 8.2.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/dist/Teaser.cjs.js +17 -51
- package/dist/Teaser.es5.js +55 -111
- package/dist/Teaser.esm.js +17 -51
- package/package.json +2 -2
package/dist/Teaser.cjs.js
CHANGED
|
@@ -18,11 +18,9 @@ const rulesets = {
|
|
|
18
18
|
if (props.showVideo && props.video && props.video.url) {
|
|
19
19
|
return 'video';
|
|
20
20
|
}
|
|
21
|
-
|
|
22
21
|
if (props.showHeadshot && props.headshot && props.indicators.isColumn) {
|
|
23
22
|
return 'headshot';
|
|
24
23
|
}
|
|
25
|
-
|
|
26
24
|
if (props.showImage && props.image && props.image.url) {
|
|
27
25
|
return 'image';
|
|
28
26
|
}
|
|
@@ -31,31 +29,27 @@ const rulesets = {
|
|
|
31
29
|
if (props.theme) {
|
|
32
30
|
return props.theme;
|
|
33
31
|
}
|
|
34
|
-
|
|
35
32
|
if (props.status === 'inprogress') {
|
|
36
33
|
return 'live';
|
|
37
34
|
}
|
|
38
|
-
|
|
39
35
|
if (props.indicators && props.indicators.isOpinion) {
|
|
40
36
|
return 'opinion';
|
|
41
37
|
}
|
|
42
|
-
|
|
43
38
|
if (props.indicators && props.indicators.isEditorsChoice) {
|
|
44
39
|
return 'highlight';
|
|
45
40
|
}
|
|
46
|
-
|
|
47
41
|
if (props.parentTheme) {
|
|
48
42
|
return props.parentTheme;
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
45
|
};
|
|
46
|
+
|
|
52
47
|
/**
|
|
53
48
|
* Rules
|
|
54
49
|
* @param {String} rule
|
|
55
50
|
* @param {Props} props
|
|
56
51
|
* @returns {String|null}
|
|
57
52
|
*/
|
|
58
|
-
|
|
59
53
|
function rules(rule, props) {
|
|
60
54
|
if (rulesets.hasOwnProperty(rule)) {
|
|
61
55
|
return rulesets[rule](props);
|
|
@@ -69,23 +63,18 @@ const theme = props => rules('theme', props);
|
|
|
69
63
|
const dynamicModifiers = props => {
|
|
70
64
|
const modifiers = [];
|
|
71
65
|
const mediaRule = media(props);
|
|
72
|
-
|
|
73
66
|
if (mediaRule) {
|
|
74
67
|
modifiers.push(`has-${mediaRule}`);
|
|
75
68
|
}
|
|
76
|
-
|
|
77
69
|
const themeRule = theme(props);
|
|
78
|
-
|
|
79
70
|
if (themeRule) {
|
|
80
71
|
modifiers.push(themeRule);
|
|
81
72
|
}
|
|
82
|
-
|
|
83
73
|
return modifiers;
|
|
84
74
|
};
|
|
85
|
-
|
|
86
75
|
var Container = (props => {
|
|
87
|
-
const computed = dynamicModifiers(props);
|
|
88
|
-
|
|
76
|
+
const computed = dynamicModifiers(props);
|
|
77
|
+
// Modifier props may be a string rather than a string[] so concat, don't spread.
|
|
89
78
|
const variants = [props.type, props.layout].concat(props.modifiers, computed);
|
|
90
79
|
const classNames = variants.filter(Boolean).map(mod => `o-teaser--${mod}`).join(' ');
|
|
91
80
|
return xEngine.h("div", {
|
|
@@ -106,7 +95,6 @@ var Content = (({
|
|
|
106
95
|
* @param {String|ReactElement} action
|
|
107
96
|
* @returns {ReactElement}
|
|
108
97
|
*/
|
|
109
|
-
|
|
110
98
|
const render = action => {
|
|
111
99
|
// Allow parent components to pass raw HTML strings
|
|
112
100
|
if (typeof action === 'string') {
|
|
@@ -119,7 +107,6 @@ const render = action => {
|
|
|
119
107
|
return action;
|
|
120
108
|
}
|
|
121
109
|
};
|
|
122
|
-
|
|
123
110
|
var CustomSlot = (({
|
|
124
111
|
customSlot
|
|
125
112
|
}) => customSlot ? xEngine.h("div", {
|
|
@@ -134,8 +121,8 @@ const ImageSizes = {
|
|
|
134
121
|
Large: 420,
|
|
135
122
|
XL: 640,
|
|
136
123
|
XXL: 1180 // max width of FT.com page
|
|
137
|
-
|
|
138
124
|
};
|
|
125
|
+
|
|
139
126
|
const Layouts = {
|
|
140
127
|
Small: 'small',
|
|
141
128
|
Large: 'large',
|
|
@@ -151,22 +138,24 @@ const OPTIONS = {
|
|
|
151
138
|
fit: 'scale-down',
|
|
152
139
|
dpr: 2
|
|
153
140
|
};
|
|
141
|
+
|
|
154
142
|
/**
|
|
155
143
|
* Image Service
|
|
156
144
|
* @param {String} url
|
|
157
145
|
* @param {Number} width
|
|
158
146
|
* @param {String} options
|
|
159
147
|
*/
|
|
160
|
-
|
|
161
148
|
function imageService(url, width, options) {
|
|
162
149
|
const imageSrc = new URL(`${BASE_URL}/${encodeURIComponent(url)}`);
|
|
163
|
-
imageSrc.search = new URLSearchParams({
|
|
150
|
+
imageSrc.search = new URLSearchParams({
|
|
151
|
+
...OPTIONS,
|
|
164
152
|
...options
|
|
165
153
|
});
|
|
166
154
|
imageSrc.searchParams.set('width', width);
|
|
167
155
|
return imageSrc.href;
|
|
168
156
|
}
|
|
169
157
|
|
|
158
|
+
// these colours are tweaked from o-colors palette colours to make headshots look less washed out
|
|
170
159
|
const DEFAULT_TINT = '054593,d6d5d3';
|
|
171
160
|
var Headshot = (({
|
|
172
161
|
headshot,
|
|
@@ -198,7 +187,6 @@ const BaseLink = ({
|
|
|
198
187
|
return xEngine.h("span", attrs, children);
|
|
199
188
|
}
|
|
200
189
|
};
|
|
201
|
-
|
|
202
190
|
var Link = (({
|
|
203
191
|
customElements = {},
|
|
204
192
|
...props
|
|
@@ -212,7 +200,6 @@ var Link = (({
|
|
|
212
200
|
* @param {{ width: Number, height: Number }} image
|
|
213
201
|
* @returns {String|null}
|
|
214
202
|
*/
|
|
215
|
-
|
|
216
203
|
const aspectRatio = ({
|
|
217
204
|
width,
|
|
218
205
|
height
|
|
@@ -221,10 +208,8 @@ const aspectRatio = ({
|
|
|
221
208
|
const ratio = 100 / width * height;
|
|
222
209
|
return ratio.toFixed(4) + '%';
|
|
223
210
|
}
|
|
224
|
-
|
|
225
211
|
return null;
|
|
226
212
|
};
|
|
227
|
-
|
|
228
213
|
const NormalImage = ({
|
|
229
214
|
src
|
|
230
215
|
}) => xEngine.h("img", {
|
|
@@ -232,7 +217,6 @@ const NormalImage = ({
|
|
|
232
217
|
src: src,
|
|
233
218
|
alt: ""
|
|
234
219
|
});
|
|
235
|
-
|
|
236
220
|
const LazyImage = ({
|
|
237
221
|
src,
|
|
238
222
|
lazyLoad
|
|
@@ -244,7 +228,6 @@ const LazyImage = ({
|
|
|
244
228
|
alt: ""
|
|
245
229
|
});
|
|
246
230
|
};
|
|
247
|
-
|
|
248
231
|
var Image = (({
|
|
249
232
|
relativeUrl,
|
|
250
233
|
url,
|
|
@@ -257,7 +240,6 @@ var Image = (({
|
|
|
257
240
|
if (!image || image && !image.url) {
|
|
258
241
|
return null;
|
|
259
242
|
}
|
|
260
|
-
|
|
261
243
|
const displayUrl = relativeUrl || url;
|
|
262
244
|
const useImageService = !(image.url.startsWith('data:') || image.url.startsWith('blob:'));
|
|
263
245
|
const options = imageSize === 'XXL' && imageHighestQuality ? {
|
|
@@ -288,11 +270,9 @@ var Image = (({
|
|
|
288
270
|
const sameId = (context = {}, id) => {
|
|
289
271
|
return id && context && context.parentId && id === context.parentId;
|
|
290
272
|
};
|
|
291
|
-
|
|
292
273
|
const sameLabel = (context = {}, label) => {
|
|
293
274
|
return label && context && context.parentLabel && label === context.parentLabel;
|
|
294
275
|
};
|
|
295
|
-
|
|
296
276
|
var MetaLink = (({
|
|
297
277
|
metaPrefixText,
|
|
298
278
|
metaLink,
|
|
@@ -353,7 +333,6 @@ const renderLink = ({
|
|
|
353
333
|
href: displayUrl
|
|
354
334
|
}, title));
|
|
355
335
|
};
|
|
356
|
-
|
|
357
336
|
var RelatedLinks = (({
|
|
358
337
|
relatedLinks = []
|
|
359
338
|
}) => relatedLinks && relatedLinks.length ? xEngine.h("ul", {
|
|
@@ -374,34 +353,31 @@ var TimeStamp = (({
|
|
|
374
353
|
* @param {Date | String | Number} date
|
|
375
354
|
* @returns {Date}
|
|
376
355
|
*/
|
|
377
|
-
|
|
378
356
|
function toDate(date) {
|
|
379
357
|
if (typeof date === 'string') {
|
|
380
358
|
return new Date(date);
|
|
381
359
|
}
|
|
382
|
-
|
|
383
360
|
if (typeof date === 'number') {
|
|
384
361
|
return new Date(date);
|
|
385
362
|
}
|
|
386
|
-
|
|
387
363
|
return date;
|
|
388
364
|
}
|
|
365
|
+
|
|
389
366
|
/**
|
|
390
367
|
* Get Relative Date
|
|
391
368
|
* @param {Date | String | Number} date
|
|
392
369
|
* @returns {Number}
|
|
393
370
|
*/
|
|
394
|
-
|
|
395
371
|
function getRelativeDate(date) {
|
|
396
372
|
return Date.now() - toDate(date).getTime();
|
|
397
373
|
}
|
|
374
|
+
|
|
398
375
|
/**
|
|
399
376
|
* Get Status
|
|
400
377
|
* @param {Date | String | Number} publishedDate
|
|
401
378
|
* @param {Date | String | Number} firstPublishedDate
|
|
402
379
|
* @returns {String}
|
|
403
380
|
*/
|
|
404
|
-
|
|
405
381
|
function getStatus(publishedDate, firstPublishedDate) {
|
|
406
382
|
if (getRelativeDate(publishedDate) < Newish) {
|
|
407
383
|
if (publishedDate === firstPublishedDate) {
|
|
@@ -410,15 +386,14 @@ function getStatus(publishedDate, firstPublishedDate) {
|
|
|
410
386
|
return 'updated';
|
|
411
387
|
}
|
|
412
388
|
}
|
|
413
|
-
|
|
414
389
|
return '';
|
|
415
390
|
}
|
|
391
|
+
|
|
416
392
|
/**
|
|
417
393
|
* Is Recent
|
|
418
394
|
* @param {Number} relativeDate
|
|
419
395
|
* @returns {Boolean}
|
|
420
396
|
*/
|
|
421
|
-
|
|
422
397
|
function isRecent(relativeDate) {
|
|
423
398
|
return relativeDate < Recent;
|
|
424
399
|
}
|
|
@@ -428,14 +403,12 @@ function isRecent(relativeDate) {
|
|
|
428
403
|
* @param {Number} date
|
|
429
404
|
* @returns {String}
|
|
430
405
|
*/
|
|
431
|
-
|
|
432
406
|
const displayTime = date => {
|
|
433
407
|
const hours = Math.floor(Math.abs(date / 3600000));
|
|
434
408
|
const plural = hours === 1 ? 'hour' : 'hours';
|
|
435
409
|
const suffix = hours === 0 ? '' : `${plural} ago`;
|
|
436
410
|
return `${hours} ${suffix}`;
|
|
437
411
|
};
|
|
438
|
-
|
|
439
412
|
var RelativeTime = (({
|
|
440
413
|
publishedDate,
|
|
441
414
|
firstPublishedDate,
|
|
@@ -478,12 +451,9 @@ var LiveBlogStatus = (({
|
|
|
478
451
|
* If same calendar day, we show relative time e.g. X hours ago or Updated X min ago
|
|
479
452
|
* If different calendar day, we show full Date time e.g. June 9, 2021
|
|
480
453
|
*/
|
|
481
|
-
|
|
482
454
|
var AlwaysShowTimestamp = (props => {
|
|
483
455
|
const localTodayDate = new Date().toISOString().substr(0, 10); // keep only the date bit
|
|
484
|
-
|
|
485
456
|
const dateToCompare = new Date(props.publishedDate).toISOString().substr(0, 10);
|
|
486
|
-
|
|
487
457
|
if (dateFns.differenceInCalendarDays(localTodayDate, dateToCompare) >= 1) {
|
|
488
458
|
return xEngine.h(TimeStamp, props);
|
|
489
459
|
} else {
|
|
@@ -497,7 +467,6 @@ var Status = (props => {
|
|
|
497
467
|
if (props.status) {
|
|
498
468
|
return xEngine.h(LiveBlogStatus, props);
|
|
499
469
|
}
|
|
500
|
-
|
|
501
470
|
if (props.publishedDate) {
|
|
502
471
|
if (props.useRelativeTimeIfToday) {
|
|
503
472
|
return xEngine.h(AlwaysShowTimestamp, props);
|
|
@@ -507,7 +476,6 @@ var Status = (props => {
|
|
|
507
476
|
return xEngine.h(TimeStamp, props);
|
|
508
477
|
}
|
|
509
478
|
}
|
|
510
|
-
|
|
511
479
|
return null;
|
|
512
480
|
});
|
|
513
481
|
|
|
@@ -543,17 +511,15 @@ var Title = (({
|
|
|
543
511
|
...props
|
|
544
512
|
}) => {
|
|
545
513
|
const displayTitle = headlineTesting && altTitle ? altTitle : title;
|
|
546
|
-
const displayUrl = relativeUrl || url;
|
|
547
|
-
|
|
514
|
+
const displayUrl = relativeUrl || url;
|
|
515
|
+
// o-labels--premium left for backwards compatibility for o-labels v3
|
|
548
516
|
const premiumClass = 'o-labels o-labels--premium o-labels--content-premium';
|
|
549
517
|
let ariaLabel;
|
|
550
|
-
|
|
551
518
|
if (props.type === 'video') {
|
|
552
519
|
ariaLabel = `Watch video ${displayTitle}`;
|
|
553
520
|
} else if (props.type === 'audio') {
|
|
554
521
|
ariaLabel = `Listen to podcast ${displayTitle}`;
|
|
555
522
|
}
|
|
556
|
-
|
|
557
523
|
return xEngine.h("div", {
|
|
558
524
|
className: "o-teaser__heading"
|
|
559
525
|
}, xEngine.h(Link, Object.assign({}, props, {
|
|
@@ -570,13 +536,14 @@ var Title = (({
|
|
|
570
536
|
}, "\xA0content")) : null);
|
|
571
537
|
});
|
|
572
538
|
|
|
539
|
+
// Re-format the data for use with o-video
|
|
573
540
|
const formatData = props => JSON.stringify({
|
|
574
541
|
renditions: [props.video],
|
|
575
542
|
mainImageUrl: props.image ? props.image.url : null
|
|
576
|
-
});
|
|
577
|
-
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
578
|
-
|
|
543
|
+
});
|
|
579
544
|
|
|
545
|
+
// To prevent React from touching the DOM after mounting… return an empty <div />
|
|
546
|
+
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
580
547
|
const Embed = props => {
|
|
581
548
|
const showGuidance = typeof props.showGuidance === 'boolean' ? props.showGuidance.toString() : 'true';
|
|
582
549
|
return xEngine.h("div", {
|
|
@@ -597,7 +564,6 @@ const Embed = props => {
|
|
|
597
564
|
"data-o-video-systemcode": props.systemCode
|
|
598
565
|
}));
|
|
599
566
|
};
|
|
600
|
-
|
|
601
567
|
var Video = (props => xEngine.h("div", {
|
|
602
568
|
className: "o-teaser__video"
|
|
603
569
|
}, xEngine.h("div", {
|
package/dist/Teaser.es5.js
CHANGED
|
@@ -18,11 +18,9 @@ var rulesets = {
|
|
|
18
18
|
if (props.showVideo && props.video && props.video.url) {
|
|
19
19
|
return 'video';
|
|
20
20
|
}
|
|
21
|
-
|
|
22
21
|
if (props.showHeadshot && props.headshot && props.indicators.isColumn) {
|
|
23
22
|
return 'headshot';
|
|
24
23
|
}
|
|
25
|
-
|
|
26
24
|
if (props.showImage && props.image && props.image.url) {
|
|
27
25
|
return 'image';
|
|
28
26
|
}
|
|
@@ -31,31 +29,27 @@ var rulesets = {
|
|
|
31
29
|
if (props.theme) {
|
|
32
30
|
return props.theme;
|
|
33
31
|
}
|
|
34
|
-
|
|
35
32
|
if (props.status === 'inprogress') {
|
|
36
33
|
return 'live';
|
|
37
34
|
}
|
|
38
|
-
|
|
39
35
|
if (props.indicators && props.indicators.isOpinion) {
|
|
40
36
|
return 'opinion';
|
|
41
37
|
}
|
|
42
|
-
|
|
43
38
|
if (props.indicators && props.indicators.isEditorsChoice) {
|
|
44
39
|
return 'highlight';
|
|
45
40
|
}
|
|
46
|
-
|
|
47
41
|
if (props.parentTheme) {
|
|
48
42
|
return props.parentTheme;
|
|
49
43
|
}
|
|
50
44
|
}
|
|
51
45
|
};
|
|
46
|
+
|
|
52
47
|
/**
|
|
53
48
|
* Rules
|
|
54
49
|
* @param {String} rule
|
|
55
50
|
* @param {Props} props
|
|
56
51
|
* @returns {String|null}
|
|
57
52
|
*/
|
|
58
|
-
|
|
59
53
|
function rules(rule, props) {
|
|
60
54
|
if (rulesets.hasOwnProperty(rule)) {
|
|
61
55
|
return rulesets[rule](props);
|
|
@@ -73,23 +67,18 @@ var theme = function theme(props) {
|
|
|
73
67
|
var dynamicModifiers = function dynamicModifiers(props) {
|
|
74
68
|
var modifiers = [];
|
|
75
69
|
var mediaRule = media(props);
|
|
76
|
-
|
|
77
70
|
if (mediaRule) {
|
|
78
71
|
modifiers.push("has-".concat(mediaRule));
|
|
79
72
|
}
|
|
80
|
-
|
|
81
73
|
var themeRule = theme(props);
|
|
82
|
-
|
|
83
74
|
if (themeRule) {
|
|
84
75
|
modifiers.push(themeRule);
|
|
85
76
|
}
|
|
86
|
-
|
|
87
77
|
return modifiers;
|
|
88
78
|
};
|
|
89
|
-
|
|
90
79
|
var Container = (function (props) {
|
|
91
|
-
var computed = dynamicModifiers(props);
|
|
92
|
-
|
|
80
|
+
var computed = dynamicModifiers(props);
|
|
81
|
+
// Modifier props may be a string rather than a string[] so concat, don't spread.
|
|
93
82
|
var variants = [props.type, props.layout].concat(props.modifiers, computed);
|
|
94
83
|
var classNames = variants.filter(Boolean).map(function (mod) {
|
|
95
84
|
return "o-teaser--".concat(mod);
|
|
@@ -103,7 +92,7 @@ var Container = (function (props) {
|
|
|
103
92
|
|
|
104
93
|
var Content = (function (_ref) {
|
|
105
94
|
var _ref$children = _ref.children,
|
|
106
|
-
|
|
95
|
+
children = _ref$children === void 0 ? [] : _ref$children;
|
|
107
96
|
return xEngine.h("div", {
|
|
108
97
|
className: "o-teaser__content"
|
|
109
98
|
}, children);
|
|
@@ -114,7 +103,6 @@ var Content = (function (_ref) {
|
|
|
114
103
|
* @param {String|ReactElement} action
|
|
115
104
|
* @returns {ReactElement}
|
|
116
105
|
*/
|
|
117
|
-
|
|
118
106
|
var render = function render(action) {
|
|
119
107
|
// Allow parent components to pass raw HTML strings
|
|
120
108
|
if (typeof action === 'string') {
|
|
@@ -127,7 +115,6 @@ var render = function render(action) {
|
|
|
127
115
|
return action;
|
|
128
116
|
}
|
|
129
117
|
};
|
|
130
|
-
|
|
131
118
|
var CustomSlot = (function (_ref) {
|
|
132
119
|
var customSlot = _ref.customSlot;
|
|
133
120
|
return customSlot ? xEngine.h("div", {
|
|
@@ -143,8 +130,8 @@ var ImageSizes = {
|
|
|
143
130
|
Large: 420,
|
|
144
131
|
XL: 640,
|
|
145
132
|
XXL: 1180 // max width of FT.com page
|
|
146
|
-
|
|
147
133
|
};
|
|
134
|
+
|
|
148
135
|
var Layouts = {
|
|
149
136
|
Small: 'small',
|
|
150
137
|
Large: 'large',
|
|
@@ -156,17 +143,14 @@ var Recent = 1000 * 60 * 60 * 4;
|
|
|
156
143
|
|
|
157
144
|
function ownKeys(object, enumerableOnly) {
|
|
158
145
|
var keys = Object.keys(object);
|
|
159
|
-
|
|
160
146
|
if (Object.getOwnPropertySymbols) {
|
|
161
147
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
162
148
|
enumerableOnly && (symbols = symbols.filter(function (sym) {
|
|
163
149
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
164
150
|
})), keys.push.apply(keys, symbols);
|
|
165
151
|
}
|
|
166
|
-
|
|
167
152
|
return keys;
|
|
168
153
|
}
|
|
169
|
-
|
|
170
154
|
function _objectSpread2(target) {
|
|
171
155
|
for (var i = 1; i < arguments.length; i++) {
|
|
172
156
|
var source = null != arguments[i] ? arguments[i] : {};
|
|
@@ -176,10 +160,8 @@ function _objectSpread2(target) {
|
|
|
176
160
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
177
161
|
});
|
|
178
162
|
}
|
|
179
|
-
|
|
180
163
|
return target;
|
|
181
164
|
}
|
|
182
|
-
|
|
183
165
|
function _defineProperty(obj, key, value) {
|
|
184
166
|
if (key in obj) {
|
|
185
167
|
Object.defineProperty(obj, key, {
|
|
@@ -191,35 +173,26 @@ function _defineProperty(obj, key, value) {
|
|
|
191
173
|
} else {
|
|
192
174
|
obj[key] = value;
|
|
193
175
|
}
|
|
194
|
-
|
|
195
176
|
return obj;
|
|
196
177
|
}
|
|
197
|
-
|
|
198
178
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
199
179
|
if (source == null) return {};
|
|
200
180
|
var target = {};
|
|
201
181
|
var sourceKeys = Object.keys(source);
|
|
202
182
|
var key, i;
|
|
203
|
-
|
|
204
183
|
for (i = 0; i < sourceKeys.length; i++) {
|
|
205
184
|
key = sourceKeys[i];
|
|
206
185
|
if (excluded.indexOf(key) >= 0) continue;
|
|
207
186
|
target[key] = source[key];
|
|
208
187
|
}
|
|
209
|
-
|
|
210
188
|
return target;
|
|
211
189
|
}
|
|
212
|
-
|
|
213
190
|
function _objectWithoutProperties(source, excluded) {
|
|
214
191
|
if (source == null) return {};
|
|
215
|
-
|
|
216
192
|
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
217
|
-
|
|
218
193
|
var key, i;
|
|
219
|
-
|
|
220
194
|
if (Object.getOwnPropertySymbols) {
|
|
221
195
|
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
222
|
-
|
|
223
196
|
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
224
197
|
key = sourceSymbolKeys[i];
|
|
225
198
|
if (excluded.indexOf(key) >= 0) continue;
|
|
@@ -227,7 +200,6 @@ function _objectWithoutProperties(source, excluded) {
|
|
|
227
200
|
target[key] = source[key];
|
|
228
201
|
}
|
|
229
202
|
}
|
|
230
|
-
|
|
231
203
|
return target;
|
|
232
204
|
}
|
|
233
205
|
|
|
@@ -237,13 +209,13 @@ var OPTIONS = {
|
|
|
237
209
|
fit: 'scale-down',
|
|
238
210
|
dpr: 2
|
|
239
211
|
};
|
|
212
|
+
|
|
240
213
|
/**
|
|
241
214
|
* Image Service
|
|
242
215
|
* @param {String} url
|
|
243
216
|
* @param {Number} width
|
|
244
217
|
* @param {String} options
|
|
245
218
|
*/
|
|
246
|
-
|
|
247
219
|
function imageService(url, width, options) {
|
|
248
220
|
var imageSrc = new URL("".concat(BASE_URL, "/").concat(encodeURIComponent(url)));
|
|
249
221
|
imageSrc.search = new URLSearchParams(_objectSpread2(_objectSpread2({}, OPTIONS), options));
|
|
@@ -251,10 +223,11 @@ function imageService(url, width, options) {
|
|
|
251
223
|
return imageSrc.href;
|
|
252
224
|
}
|
|
253
225
|
|
|
226
|
+
// these colours are tweaked from o-colors palette colours to make headshots look less washed out
|
|
254
227
|
var DEFAULT_TINT = '054593,d6d5d3';
|
|
255
228
|
var Headshot = (function (_ref) {
|
|
256
229
|
var headshot = _ref.headshot,
|
|
257
|
-
|
|
230
|
+
headshotTint = _ref.headshotTint;
|
|
258
231
|
var options = {
|
|
259
232
|
tint: "".concat(headshotTint || DEFAULT_TINT)
|
|
260
233
|
};
|
|
@@ -269,13 +242,11 @@ var Headshot = (function (_ref) {
|
|
|
269
242
|
});
|
|
270
243
|
|
|
271
244
|
var _excluded = ["customElements"];
|
|
272
|
-
|
|
273
245
|
var BaseLink = function BaseLink(_ref) {
|
|
274
246
|
var url = _ref.url,
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
247
|
+
_ref$attrs = _ref.attrs,
|
|
248
|
+
attrs = _ref$attrs === void 0 ? {} : _ref$attrs,
|
|
249
|
+
children = _ref.children;
|
|
279
250
|
if (url) {
|
|
280
251
|
return xEngine.h("a", Object.assign({
|
|
281
252
|
href: url
|
|
@@ -284,35 +255,30 @@ var BaseLink = function BaseLink(_ref) {
|
|
|
284
255
|
return xEngine.h("span", attrs, children);
|
|
285
256
|
}
|
|
286
257
|
};
|
|
287
|
-
|
|
288
258
|
var Link = (function (_ref2) {
|
|
289
259
|
var _ref2$customElements = _ref2.customElements,
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
260
|
+
customElements = _ref2$customElements === void 0 ? {} : _ref2$customElements,
|
|
261
|
+
props = _objectWithoutProperties(_ref2, _excluded);
|
|
293
262
|
var Link = customElements.Link || BaseLink;
|
|
294
263
|
return xEngine.h(Link, props);
|
|
295
264
|
});
|
|
296
265
|
|
|
297
266
|
var _excluded$1 = ["relativeUrl", "url", "image", "imageSize", "imageLazyLoad", "imageHighestQuality"];
|
|
267
|
+
|
|
298
268
|
/**
|
|
299
269
|
* Aspect Ratio
|
|
300
270
|
* @param {{ width: Number, height: Number }} image
|
|
301
271
|
* @returns {String|null}
|
|
302
272
|
*/
|
|
303
|
-
|
|
304
273
|
var aspectRatio = function aspectRatio(_ref) {
|
|
305
274
|
var width = _ref.width,
|
|
306
|
-
|
|
307
|
-
|
|
275
|
+
height = _ref.height;
|
|
308
276
|
if (typeof width === 'number' && typeof height === 'number') {
|
|
309
277
|
var ratio = 100 / width * height;
|
|
310
278
|
return ratio.toFixed(4) + '%';
|
|
311
279
|
}
|
|
312
|
-
|
|
313
280
|
return null;
|
|
314
281
|
};
|
|
315
|
-
|
|
316
282
|
var NormalImage = function NormalImage(_ref2) {
|
|
317
283
|
var src = _ref2.src;
|
|
318
284
|
return xEngine.h("img", {
|
|
@@ -321,10 +287,9 @@ var NormalImage = function NormalImage(_ref2) {
|
|
|
321
287
|
alt: ""
|
|
322
288
|
});
|
|
323
289
|
};
|
|
324
|
-
|
|
325
290
|
var LazyImage = function LazyImage(_ref3) {
|
|
326
291
|
var src = _ref3.src,
|
|
327
|
-
|
|
292
|
+
lazyLoad = _ref3.lazyLoad;
|
|
328
293
|
var lazyClassName = typeof lazyLoad === 'string' ? lazyLoad : '';
|
|
329
294
|
return xEngine.h("img", {
|
|
330
295
|
className: "o-teaser__image ".concat(lazyClassName),
|
|
@@ -332,20 +297,17 @@ var LazyImage = function LazyImage(_ref3) {
|
|
|
332
297
|
alt: ""
|
|
333
298
|
});
|
|
334
299
|
};
|
|
335
|
-
|
|
336
300
|
var Image = (function (_ref4) {
|
|
337
301
|
var relativeUrl = _ref4.relativeUrl,
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
302
|
+
url = _ref4.url,
|
|
303
|
+
image = _ref4.image,
|
|
304
|
+
imageSize = _ref4.imageSize,
|
|
305
|
+
imageLazyLoad = _ref4.imageLazyLoad,
|
|
306
|
+
imageHighestQuality = _ref4.imageHighestQuality,
|
|
307
|
+
props = _objectWithoutProperties(_ref4, _excluded$1);
|
|
345
308
|
if (!image || image && !image.url) {
|
|
346
309
|
return null;
|
|
347
310
|
}
|
|
348
|
-
|
|
349
311
|
var displayUrl = relativeUrl || url;
|
|
350
312
|
var useImageService = !(image.url.startsWith('data:') || image.url.startsWith('blob:'));
|
|
351
313
|
var options = imageSize === 'XXL' && imageHighestQuality ? {
|
|
@@ -378,19 +340,17 @@ var sameId = function sameId() {
|
|
|
378
340
|
var id = arguments.length > 1 ? arguments[1] : undefined;
|
|
379
341
|
return id && context && context.parentId && id === context.parentId;
|
|
380
342
|
};
|
|
381
|
-
|
|
382
343
|
var sameLabel = function sameLabel() {
|
|
383
344
|
var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
384
345
|
var label = arguments.length > 1 ? arguments[1] : undefined;
|
|
385
346
|
return label && context && context.parentLabel && label === context.parentLabel;
|
|
386
347
|
};
|
|
387
|
-
|
|
388
348
|
var MetaLink = (function (_ref) {
|
|
389
349
|
var metaPrefixText = _ref.metaPrefixText,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
350
|
+
metaLink = _ref.metaLink,
|
|
351
|
+
metaAltLink = _ref.metaAltLink,
|
|
352
|
+
metaSuffixText = _ref.metaSuffixText,
|
|
353
|
+
context = _ref.context;
|
|
394
354
|
var showPrefixText = metaPrefixText && !sameLabel(context, metaPrefixText);
|
|
395
355
|
var showSuffixText = metaSuffixText && !sameLabel(context, metaSuffixText);
|
|
396
356
|
var linkId = metaLink && metaLink.id;
|
|
@@ -413,7 +373,7 @@ var MetaLink = (function (_ref) {
|
|
|
413
373
|
|
|
414
374
|
var Promoted = (function (_ref) {
|
|
415
375
|
var promotedPrefixText = _ref.promotedPrefixText,
|
|
416
|
-
|
|
376
|
+
promotedSuffixText = _ref.promotedSuffixText;
|
|
417
377
|
return xEngine.h("div", {
|
|
418
378
|
className: "o-teaser__meta"
|
|
419
379
|
}, xEngine.h("span", {
|
|
@@ -430,10 +390,10 @@ var Meta = (function (props) {
|
|
|
430
390
|
|
|
431
391
|
var renderLink = function renderLink(_ref, i) {
|
|
432
392
|
var id = _ref.id,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
393
|
+
type = _ref.type,
|
|
394
|
+
title = _ref.title,
|
|
395
|
+
url = _ref.url,
|
|
396
|
+
relativeUrl = _ref.relativeUrl;
|
|
437
397
|
var displayUrl = relativeUrl || url;
|
|
438
398
|
return xEngine.h("li", {
|
|
439
399
|
key: "related-".concat(i),
|
|
@@ -444,10 +404,9 @@ var renderLink = function renderLink(_ref, i) {
|
|
|
444
404
|
href: displayUrl
|
|
445
405
|
}, title));
|
|
446
406
|
};
|
|
447
|
-
|
|
448
407
|
var RelatedLinks = (function (_ref2) {
|
|
449
408
|
var _ref2$relatedLinks = _ref2.relatedLinks,
|
|
450
|
-
|
|
409
|
+
relatedLinks = _ref2$relatedLinks === void 0 ? [] : _ref2$relatedLinks;
|
|
451
410
|
return relatedLinks && relatedLinks.length ? xEngine.h("ul", {
|
|
452
411
|
className: "o-teaser__related"
|
|
453
412
|
}, relatedLinks.map(renderLink)) : null;
|
|
@@ -468,34 +427,31 @@ var TimeStamp = (function (_ref) {
|
|
|
468
427
|
* @param {Date | String | Number} date
|
|
469
428
|
* @returns {Date}
|
|
470
429
|
*/
|
|
471
|
-
|
|
472
430
|
function toDate(date) {
|
|
473
431
|
if (typeof date === 'string') {
|
|
474
432
|
return new Date(date);
|
|
475
433
|
}
|
|
476
|
-
|
|
477
434
|
if (typeof date === 'number') {
|
|
478
435
|
return new Date(date);
|
|
479
436
|
}
|
|
480
|
-
|
|
481
437
|
return date;
|
|
482
438
|
}
|
|
439
|
+
|
|
483
440
|
/**
|
|
484
441
|
* Get Relative Date
|
|
485
442
|
* @param {Date | String | Number} date
|
|
486
443
|
* @returns {Number}
|
|
487
444
|
*/
|
|
488
|
-
|
|
489
445
|
function getRelativeDate(date) {
|
|
490
446
|
return Date.now() - toDate(date).getTime();
|
|
491
447
|
}
|
|
448
|
+
|
|
492
449
|
/**
|
|
493
450
|
* Get Status
|
|
494
451
|
* @param {Date | String | Number} publishedDate
|
|
495
452
|
* @param {Date | String | Number} firstPublishedDate
|
|
496
453
|
* @returns {String}
|
|
497
454
|
*/
|
|
498
|
-
|
|
499
455
|
function getStatus(publishedDate, firstPublishedDate) {
|
|
500
456
|
if (getRelativeDate(publishedDate) < Newish) {
|
|
501
457
|
if (publishedDate === firstPublishedDate) {
|
|
@@ -504,15 +460,14 @@ function getStatus(publishedDate, firstPublishedDate) {
|
|
|
504
460
|
return 'updated';
|
|
505
461
|
}
|
|
506
462
|
}
|
|
507
|
-
|
|
508
463
|
return '';
|
|
509
464
|
}
|
|
465
|
+
|
|
510
466
|
/**
|
|
511
467
|
* Is Recent
|
|
512
468
|
* @param {Number} relativeDate
|
|
513
469
|
* @returns {Boolean}
|
|
514
470
|
*/
|
|
515
|
-
|
|
516
471
|
function isRecent(relativeDate) {
|
|
517
472
|
return relativeDate < Recent;
|
|
518
473
|
}
|
|
@@ -522,19 +477,17 @@ function isRecent(relativeDate) {
|
|
|
522
477
|
* @param {Number} date
|
|
523
478
|
* @returns {String}
|
|
524
479
|
*/
|
|
525
|
-
|
|
526
480
|
var displayTime = function displayTime(date) {
|
|
527
481
|
var hours = Math.floor(Math.abs(date / 3600000));
|
|
528
482
|
var plural = hours === 1 ? 'hour' : 'hours';
|
|
529
483
|
var suffix = hours === 0 ? '' : "".concat(plural, " ago");
|
|
530
484
|
return "".concat(hours, " ").concat(suffix);
|
|
531
485
|
};
|
|
532
|
-
|
|
533
486
|
var RelativeTime = (function (_ref) {
|
|
534
487
|
var publishedDate = _ref.publishedDate,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
488
|
+
firstPublishedDate = _ref.firstPublishedDate,
|
|
489
|
+
_ref$showAlways = _ref.showAlways,
|
|
490
|
+
showAlways = _ref$showAlways === void 0 ? false : _ref$showAlways;
|
|
538
491
|
var relativeDate = getRelativeDate(publishedDate);
|
|
539
492
|
var status = getStatus(publishedDate, firstPublishedDate);
|
|
540
493
|
return showAlways === true || isRecent(relativeDate) ? xEngine.h("div", {
|
|
@@ -573,12 +526,9 @@ var LiveBlogStatus = (function (_ref) {
|
|
|
573
526
|
* If same calendar day, we show relative time e.g. X hours ago or Updated X min ago
|
|
574
527
|
* If different calendar day, we show full Date time e.g. June 9, 2021
|
|
575
528
|
*/
|
|
576
|
-
|
|
577
529
|
var AlwaysShowTimestamp = (function (props) {
|
|
578
530
|
var localTodayDate = new Date().toISOString().substr(0, 10); // keep only the date bit
|
|
579
|
-
|
|
580
531
|
var dateToCompare = new Date(props.publishedDate).toISOString().substr(0, 10);
|
|
581
|
-
|
|
582
532
|
if (dateFns.differenceInCalendarDays(localTodayDate, dateToCompare) >= 1) {
|
|
583
533
|
return xEngine.h(TimeStamp, props);
|
|
584
534
|
} else {
|
|
@@ -592,7 +542,6 @@ var Status = (function (props) {
|
|
|
592
542
|
if (props.status) {
|
|
593
543
|
return xEngine.h(LiveBlogStatus, props);
|
|
594
544
|
}
|
|
595
|
-
|
|
596
545
|
if (props.publishedDate) {
|
|
597
546
|
if (props.useRelativeTimeIfToday) {
|
|
598
547
|
return xEngine.h(AlwaysShowTimestamp, props);
|
|
@@ -602,19 +551,17 @@ var Status = (function (props) {
|
|
|
602
551
|
return xEngine.h(TimeStamp, props);
|
|
603
552
|
}
|
|
604
553
|
}
|
|
605
|
-
|
|
606
554
|
return null;
|
|
607
555
|
});
|
|
608
556
|
|
|
609
557
|
var _excluded$2 = ["standfirst", "altStandfirst", "headlineTesting", "relativeUrl", "url"];
|
|
610
558
|
var Standfirst = (function (_ref) {
|
|
611
559
|
var standfirst = _ref.standfirst,
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
560
|
+
altStandfirst = _ref.altStandfirst,
|
|
561
|
+
headlineTesting = _ref.headlineTesting,
|
|
562
|
+
relativeUrl = _ref.relativeUrl,
|
|
563
|
+
url = _ref.url,
|
|
564
|
+
props = _objectWithoutProperties(_ref, _excluded$2);
|
|
618
565
|
var displayStandfirst = headlineTesting && altStandfirst ? altStandfirst : standfirst;
|
|
619
566
|
var displayUrl = relativeUrl || url;
|
|
620
567
|
return displayStandfirst ? xEngine.h("p", {
|
|
@@ -632,25 +579,22 @@ var Standfirst = (function (_ref) {
|
|
|
632
579
|
var _excluded$3 = ["title", "altTitle", "headlineTesting", "relativeUrl", "url", "indicators"];
|
|
633
580
|
var Title = (function (_ref) {
|
|
634
581
|
var title = _ref.title,
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
582
|
+
altTitle = _ref.altTitle,
|
|
583
|
+
headlineTesting = _ref.headlineTesting,
|
|
584
|
+
relativeUrl = _ref.relativeUrl,
|
|
585
|
+
url = _ref.url,
|
|
586
|
+
indicators = _ref.indicators,
|
|
587
|
+
props = _objectWithoutProperties(_ref, _excluded$3);
|
|
642
588
|
var displayTitle = headlineTesting && altTitle ? altTitle : title;
|
|
643
|
-
var displayUrl = relativeUrl || url;
|
|
644
|
-
|
|
589
|
+
var displayUrl = relativeUrl || url;
|
|
590
|
+
// o-labels--premium left for backwards compatibility for o-labels v3
|
|
645
591
|
var premiumClass = 'o-labels o-labels--premium o-labels--content-premium';
|
|
646
592
|
var ariaLabel;
|
|
647
|
-
|
|
648
593
|
if (props.type === 'video') {
|
|
649
594
|
ariaLabel = "Watch video ".concat(displayTitle);
|
|
650
595
|
} else if (props.type === 'audio') {
|
|
651
596
|
ariaLabel = "Listen to podcast ".concat(displayTitle);
|
|
652
597
|
}
|
|
653
|
-
|
|
654
598
|
return xEngine.h("div", {
|
|
655
599
|
className: "o-teaser__heading"
|
|
656
600
|
}, xEngine.h(Link, Object.assign({}, props, {
|
|
@@ -667,15 +611,16 @@ var Title = (function (_ref) {
|
|
|
667
611
|
}, "\xA0content")) : null);
|
|
668
612
|
});
|
|
669
613
|
|
|
614
|
+
// Re-format the data for use with o-video
|
|
670
615
|
var formatData = function formatData(props) {
|
|
671
616
|
return JSON.stringify({
|
|
672
617
|
renditions: [props.video],
|
|
673
618
|
mainImageUrl: props.image ? props.image.url : null
|
|
674
619
|
});
|
|
675
|
-
};
|
|
676
|
-
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
677
|
-
|
|
620
|
+
};
|
|
678
621
|
|
|
622
|
+
// To prevent React from touching the DOM after mounting… return an empty <div />
|
|
623
|
+
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
679
624
|
var Embed = function Embed(props) {
|
|
680
625
|
var showGuidance = typeof props.showGuidance === 'boolean' ? props.showGuidance.toString() : 'true';
|
|
681
626
|
return xEngine.h("div", {
|
|
@@ -696,7 +641,6 @@ var Embed = function Embed(props) {
|
|
|
696
641
|
"data-o-video-systemcode": props.systemCode
|
|
697
642
|
}));
|
|
698
643
|
};
|
|
699
|
-
|
|
700
644
|
var Video = (function (props) {
|
|
701
645
|
return xEngine.h("div", {
|
|
702
646
|
className: "o-teaser__video"
|
package/dist/Teaser.esm.js
CHANGED
|
@@ -12,11 +12,9 @@ const rulesets = {
|
|
|
12
12
|
if (props.showVideo && props.video && props.video.url) {
|
|
13
13
|
return 'video';
|
|
14
14
|
}
|
|
15
|
-
|
|
16
15
|
if (props.showHeadshot && props.headshot && props.indicators.isColumn) {
|
|
17
16
|
return 'headshot';
|
|
18
17
|
}
|
|
19
|
-
|
|
20
18
|
if (props.showImage && props.image && props.image.url) {
|
|
21
19
|
return 'image';
|
|
22
20
|
}
|
|
@@ -25,31 +23,27 @@ const rulesets = {
|
|
|
25
23
|
if (props.theme) {
|
|
26
24
|
return props.theme;
|
|
27
25
|
}
|
|
28
|
-
|
|
29
26
|
if (props.status === 'inprogress') {
|
|
30
27
|
return 'live';
|
|
31
28
|
}
|
|
32
|
-
|
|
33
29
|
if (props.indicators && props.indicators.isOpinion) {
|
|
34
30
|
return 'opinion';
|
|
35
31
|
}
|
|
36
|
-
|
|
37
32
|
if (props.indicators && props.indicators.isEditorsChoice) {
|
|
38
33
|
return 'highlight';
|
|
39
34
|
}
|
|
40
|
-
|
|
41
35
|
if (props.parentTheme) {
|
|
42
36
|
return props.parentTheme;
|
|
43
37
|
}
|
|
44
38
|
}
|
|
45
39
|
};
|
|
40
|
+
|
|
46
41
|
/**
|
|
47
42
|
* Rules
|
|
48
43
|
* @param {String} rule
|
|
49
44
|
* @param {Props} props
|
|
50
45
|
* @returns {String|null}
|
|
51
46
|
*/
|
|
52
|
-
|
|
53
47
|
function rules(rule, props) {
|
|
54
48
|
if (rulesets.hasOwnProperty(rule)) {
|
|
55
49
|
return rulesets[rule](props);
|
|
@@ -63,23 +57,18 @@ const theme = props => rules('theme', props);
|
|
|
63
57
|
const dynamicModifiers = props => {
|
|
64
58
|
const modifiers = [];
|
|
65
59
|
const mediaRule = media(props);
|
|
66
|
-
|
|
67
60
|
if (mediaRule) {
|
|
68
61
|
modifiers.push(`has-${mediaRule}`);
|
|
69
62
|
}
|
|
70
|
-
|
|
71
63
|
const themeRule = theme(props);
|
|
72
|
-
|
|
73
64
|
if (themeRule) {
|
|
74
65
|
modifiers.push(themeRule);
|
|
75
66
|
}
|
|
76
|
-
|
|
77
67
|
return modifiers;
|
|
78
68
|
};
|
|
79
|
-
|
|
80
69
|
var Container = (props => {
|
|
81
|
-
const computed = dynamicModifiers(props);
|
|
82
|
-
|
|
70
|
+
const computed = dynamicModifiers(props);
|
|
71
|
+
// Modifier props may be a string rather than a string[] so concat, don't spread.
|
|
83
72
|
const variants = [props.type, props.layout].concat(props.modifiers, computed);
|
|
84
73
|
const classNames = variants.filter(Boolean).map(mod => `o-teaser--${mod}`).join(' ');
|
|
85
74
|
return h("div", {
|
|
@@ -100,7 +89,6 @@ var Content = (({
|
|
|
100
89
|
* @param {String|ReactElement} action
|
|
101
90
|
* @returns {ReactElement}
|
|
102
91
|
*/
|
|
103
|
-
|
|
104
92
|
const render = action => {
|
|
105
93
|
// Allow parent components to pass raw HTML strings
|
|
106
94
|
if (typeof action === 'string') {
|
|
@@ -113,7 +101,6 @@ const render = action => {
|
|
|
113
101
|
return action;
|
|
114
102
|
}
|
|
115
103
|
};
|
|
116
|
-
|
|
117
104
|
var CustomSlot = (({
|
|
118
105
|
customSlot
|
|
119
106
|
}) => customSlot ? h("div", {
|
|
@@ -128,8 +115,8 @@ const ImageSizes = {
|
|
|
128
115
|
Large: 420,
|
|
129
116
|
XL: 640,
|
|
130
117
|
XXL: 1180 // max width of FT.com page
|
|
131
|
-
|
|
132
118
|
};
|
|
119
|
+
|
|
133
120
|
const Layouts = {
|
|
134
121
|
Small: 'small',
|
|
135
122
|
Large: 'large',
|
|
@@ -145,22 +132,24 @@ const OPTIONS = {
|
|
|
145
132
|
fit: 'scale-down',
|
|
146
133
|
dpr: 2
|
|
147
134
|
};
|
|
135
|
+
|
|
148
136
|
/**
|
|
149
137
|
* Image Service
|
|
150
138
|
* @param {String} url
|
|
151
139
|
* @param {Number} width
|
|
152
140
|
* @param {String} options
|
|
153
141
|
*/
|
|
154
|
-
|
|
155
142
|
function imageService(url, width, options) {
|
|
156
143
|
const imageSrc = new URL(`${BASE_URL}/${encodeURIComponent(url)}`);
|
|
157
|
-
imageSrc.search = new URLSearchParams({
|
|
144
|
+
imageSrc.search = new URLSearchParams({
|
|
145
|
+
...OPTIONS,
|
|
158
146
|
...options
|
|
159
147
|
});
|
|
160
148
|
imageSrc.searchParams.set('width', width);
|
|
161
149
|
return imageSrc.href;
|
|
162
150
|
}
|
|
163
151
|
|
|
152
|
+
// these colours are tweaked from o-colors palette colours to make headshots look less washed out
|
|
164
153
|
const DEFAULT_TINT = '054593,d6d5d3';
|
|
165
154
|
var Headshot = (({
|
|
166
155
|
headshot,
|
|
@@ -192,7 +181,6 @@ const BaseLink = ({
|
|
|
192
181
|
return h("span", attrs, children);
|
|
193
182
|
}
|
|
194
183
|
};
|
|
195
|
-
|
|
196
184
|
var Link = (({
|
|
197
185
|
customElements = {},
|
|
198
186
|
...props
|
|
@@ -206,7 +194,6 @@ var Link = (({
|
|
|
206
194
|
* @param {{ width: Number, height: Number }} image
|
|
207
195
|
* @returns {String|null}
|
|
208
196
|
*/
|
|
209
|
-
|
|
210
197
|
const aspectRatio = ({
|
|
211
198
|
width,
|
|
212
199
|
height
|
|
@@ -215,10 +202,8 @@ const aspectRatio = ({
|
|
|
215
202
|
const ratio = 100 / width * height;
|
|
216
203
|
return ratio.toFixed(4) + '%';
|
|
217
204
|
}
|
|
218
|
-
|
|
219
205
|
return null;
|
|
220
206
|
};
|
|
221
|
-
|
|
222
207
|
const NormalImage = ({
|
|
223
208
|
src
|
|
224
209
|
}) => h("img", {
|
|
@@ -226,7 +211,6 @@ const NormalImage = ({
|
|
|
226
211
|
src: src,
|
|
227
212
|
alt: ""
|
|
228
213
|
});
|
|
229
|
-
|
|
230
214
|
const LazyImage = ({
|
|
231
215
|
src,
|
|
232
216
|
lazyLoad
|
|
@@ -238,7 +222,6 @@ const LazyImage = ({
|
|
|
238
222
|
alt: ""
|
|
239
223
|
});
|
|
240
224
|
};
|
|
241
|
-
|
|
242
225
|
var Image = (({
|
|
243
226
|
relativeUrl,
|
|
244
227
|
url,
|
|
@@ -251,7 +234,6 @@ var Image = (({
|
|
|
251
234
|
if (!image || image && !image.url) {
|
|
252
235
|
return null;
|
|
253
236
|
}
|
|
254
|
-
|
|
255
237
|
const displayUrl = relativeUrl || url;
|
|
256
238
|
const useImageService = !(image.url.startsWith('data:') || image.url.startsWith('blob:'));
|
|
257
239
|
const options = imageSize === 'XXL' && imageHighestQuality ? {
|
|
@@ -282,11 +264,9 @@ var Image = (({
|
|
|
282
264
|
const sameId = (context = {}, id) => {
|
|
283
265
|
return id && context && context.parentId && id === context.parentId;
|
|
284
266
|
};
|
|
285
|
-
|
|
286
267
|
const sameLabel = (context = {}, label) => {
|
|
287
268
|
return label && context && context.parentLabel && label === context.parentLabel;
|
|
288
269
|
};
|
|
289
|
-
|
|
290
270
|
var MetaLink = (({
|
|
291
271
|
metaPrefixText,
|
|
292
272
|
metaLink,
|
|
@@ -347,7 +327,6 @@ const renderLink = ({
|
|
|
347
327
|
href: displayUrl
|
|
348
328
|
}, title));
|
|
349
329
|
};
|
|
350
|
-
|
|
351
330
|
var RelatedLinks = (({
|
|
352
331
|
relatedLinks = []
|
|
353
332
|
}) => relatedLinks && relatedLinks.length ? h("ul", {
|
|
@@ -368,34 +347,31 @@ var TimeStamp = (({
|
|
|
368
347
|
* @param {Date | String | Number} date
|
|
369
348
|
* @returns {Date}
|
|
370
349
|
*/
|
|
371
|
-
|
|
372
350
|
function toDate(date) {
|
|
373
351
|
if (typeof date === 'string') {
|
|
374
352
|
return new Date(date);
|
|
375
353
|
}
|
|
376
|
-
|
|
377
354
|
if (typeof date === 'number') {
|
|
378
355
|
return new Date(date);
|
|
379
356
|
}
|
|
380
|
-
|
|
381
357
|
return date;
|
|
382
358
|
}
|
|
359
|
+
|
|
383
360
|
/**
|
|
384
361
|
* Get Relative Date
|
|
385
362
|
* @param {Date | String | Number} date
|
|
386
363
|
* @returns {Number}
|
|
387
364
|
*/
|
|
388
|
-
|
|
389
365
|
function getRelativeDate(date) {
|
|
390
366
|
return Date.now() - toDate(date).getTime();
|
|
391
367
|
}
|
|
368
|
+
|
|
392
369
|
/**
|
|
393
370
|
* Get Status
|
|
394
371
|
* @param {Date | String | Number} publishedDate
|
|
395
372
|
* @param {Date | String | Number} firstPublishedDate
|
|
396
373
|
* @returns {String}
|
|
397
374
|
*/
|
|
398
|
-
|
|
399
375
|
function getStatus(publishedDate, firstPublishedDate) {
|
|
400
376
|
if (getRelativeDate(publishedDate) < Newish) {
|
|
401
377
|
if (publishedDate === firstPublishedDate) {
|
|
@@ -404,15 +380,14 @@ function getStatus(publishedDate, firstPublishedDate) {
|
|
|
404
380
|
return 'updated';
|
|
405
381
|
}
|
|
406
382
|
}
|
|
407
|
-
|
|
408
383
|
return '';
|
|
409
384
|
}
|
|
385
|
+
|
|
410
386
|
/**
|
|
411
387
|
* Is Recent
|
|
412
388
|
* @param {Number} relativeDate
|
|
413
389
|
* @returns {Boolean}
|
|
414
390
|
*/
|
|
415
|
-
|
|
416
391
|
function isRecent(relativeDate) {
|
|
417
392
|
return relativeDate < Recent;
|
|
418
393
|
}
|
|
@@ -422,14 +397,12 @@ function isRecent(relativeDate) {
|
|
|
422
397
|
* @param {Number} date
|
|
423
398
|
* @returns {String}
|
|
424
399
|
*/
|
|
425
|
-
|
|
426
400
|
const displayTime = date => {
|
|
427
401
|
const hours = Math.floor(Math.abs(date / 3600000));
|
|
428
402
|
const plural = hours === 1 ? 'hour' : 'hours';
|
|
429
403
|
const suffix = hours === 0 ? '' : `${plural} ago`;
|
|
430
404
|
return `${hours} ${suffix}`;
|
|
431
405
|
};
|
|
432
|
-
|
|
433
406
|
var RelativeTime = (({
|
|
434
407
|
publishedDate,
|
|
435
408
|
firstPublishedDate,
|
|
@@ -472,12 +445,9 @@ var LiveBlogStatus = (({
|
|
|
472
445
|
* If same calendar day, we show relative time e.g. X hours ago or Updated X min ago
|
|
473
446
|
* If different calendar day, we show full Date time e.g. June 9, 2021
|
|
474
447
|
*/
|
|
475
|
-
|
|
476
448
|
var AlwaysShowTimestamp = (props => {
|
|
477
449
|
const localTodayDate = new Date().toISOString().substr(0, 10); // keep only the date bit
|
|
478
|
-
|
|
479
450
|
const dateToCompare = new Date(props.publishedDate).toISOString().substr(0, 10);
|
|
480
|
-
|
|
481
451
|
if (differenceInCalendarDays(localTodayDate, dateToCompare) >= 1) {
|
|
482
452
|
return h(TimeStamp, props);
|
|
483
453
|
} else {
|
|
@@ -491,7 +461,6 @@ var Status = (props => {
|
|
|
491
461
|
if (props.status) {
|
|
492
462
|
return h(LiveBlogStatus, props);
|
|
493
463
|
}
|
|
494
|
-
|
|
495
464
|
if (props.publishedDate) {
|
|
496
465
|
if (props.useRelativeTimeIfToday) {
|
|
497
466
|
return h(AlwaysShowTimestamp, props);
|
|
@@ -501,7 +470,6 @@ var Status = (props => {
|
|
|
501
470
|
return h(TimeStamp, props);
|
|
502
471
|
}
|
|
503
472
|
}
|
|
504
|
-
|
|
505
473
|
return null;
|
|
506
474
|
});
|
|
507
475
|
|
|
@@ -537,17 +505,15 @@ var Title = (({
|
|
|
537
505
|
...props
|
|
538
506
|
}) => {
|
|
539
507
|
const displayTitle = headlineTesting && altTitle ? altTitle : title;
|
|
540
|
-
const displayUrl = relativeUrl || url;
|
|
541
|
-
|
|
508
|
+
const displayUrl = relativeUrl || url;
|
|
509
|
+
// o-labels--premium left for backwards compatibility for o-labels v3
|
|
542
510
|
const premiumClass = 'o-labels o-labels--premium o-labels--content-premium';
|
|
543
511
|
let ariaLabel;
|
|
544
|
-
|
|
545
512
|
if (props.type === 'video') {
|
|
546
513
|
ariaLabel = `Watch video ${displayTitle}`;
|
|
547
514
|
} else if (props.type === 'audio') {
|
|
548
515
|
ariaLabel = `Listen to podcast ${displayTitle}`;
|
|
549
516
|
}
|
|
550
|
-
|
|
551
517
|
return h("div", {
|
|
552
518
|
className: "o-teaser__heading"
|
|
553
519
|
}, h(Link, Object.assign({}, props, {
|
|
@@ -564,13 +530,14 @@ var Title = (({
|
|
|
564
530
|
}, "\xA0content")) : null);
|
|
565
531
|
});
|
|
566
532
|
|
|
533
|
+
// Re-format the data for use with o-video
|
|
567
534
|
const formatData = props => JSON.stringify({
|
|
568
535
|
renditions: [props.video],
|
|
569
536
|
mainImageUrl: props.image ? props.image.url : null
|
|
570
|
-
});
|
|
571
|
-
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
572
|
-
|
|
537
|
+
});
|
|
573
538
|
|
|
539
|
+
// To prevent React from touching the DOM after mounting… return an empty <div />
|
|
540
|
+
// <https://reactjs.org/docs/integrating-with-other-libraries.html>
|
|
574
541
|
const Embed = props => {
|
|
575
542
|
const showGuidance = typeof props.showGuidance === 'boolean' ? props.showGuidance.toString() : 'true';
|
|
576
543
|
return h("div", {
|
|
@@ -591,7 +558,6 @@ const Embed = props => {
|
|
|
591
558
|
"data-o-video-systemcode": props.systemCode
|
|
592
559
|
}));
|
|
593
560
|
};
|
|
594
|
-
|
|
595
561
|
var Video = (props => h("div", {
|
|
596
562
|
className: "o-teaser__video"
|
|
597
563
|
}, h("div", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/x-teaser",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "This module provides templates for use with o-teaser. Teasers are used to present content.",
|
|
5
5
|
"source": "src/Teaser.jsx",
|
|
6
6
|
"main": "dist/Teaser.cjs.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"author": "",
|
|
19
19
|
"license": "ISC",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@financial-times/x-engine": "^8.
|
|
21
|
+
"@financial-times/x-engine": "^8.2.0",
|
|
22
22
|
"date-fns": "^1.29.0",
|
|
23
23
|
"dateformat": "^3.0.3"
|
|
24
24
|
},
|