@financial-times/cp-content-pipeline-ui 6.9.1 → 6.10.0-beta.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 +17 -0
- package/lib/components/BackToTopButton/client/index.d.ts +1 -0
- package/lib/components/BackToTopButton/client/index.js +7 -1
- package/lib/components/BackToTopButton/client/index.js.map +1 -1
- package/lib/components/Body/index.test.js +9 -0
- package/lib/components/Body/index.test.js.map +1 -1
- package/lib/components/Clip/client/index.d.ts +2 -0
- package/lib/components/Clip/client/index.js +40 -27
- package/lib/components/Clip/client/index.js.map +1 -1
- package/lib/components/Clip/client/progressBar.js +4 -2
- package/lib/components/Clip/client/progressBar.js.map +1 -1
- package/lib/components/Clip/components/ClipTag.js +1 -1
- package/lib/components/Clip/components/ClipTag.js.map +1 -1
- package/lib/components/Clip/components/Container.js +2 -2
- package/lib/components/Clip/components/Container.js.map +1 -1
- package/lib/components/Clip/template/index.js +0 -1
- package/lib/components/Clip/template/index.js.map +1 -1
- package/lib/components/Clip/test/index.spec.js +21 -9
- package/lib/components/Clip/test/index.spec.js.map +1 -1
- package/lib/components/Expander/client/index.d.ts +49 -0
- package/lib/components/Expander/client/index.js +124 -0
- package/lib/components/Expander/client/index.js.map +1 -0
- package/lib/components/Expander/index.d.ts +15 -0
- package/lib/components/Expander/index.js +27 -0
- package/lib/components/Expander/index.js.map +1 -0
- package/lib/components/Expander/test/client/index.spec.d.ts +1 -0
- package/lib/components/Expander/test/client/index.spec.js +103 -0
- package/lib/components/Expander/test/client/index.spec.js.map +1 -0
- package/lib/components/Expander/test/index.spec.d.ts +1 -0
- package/lib/components/Expander/test/index.spec.js +57 -0
- package/lib/components/Expander/test/index.spec.js.map +1 -0
- package/lib/components/Expander/test/snapshot.spec.d.ts +1 -0
- package/lib/components/Expander/test/snapshot.spec.js +63 -0
- package/lib/components/Expander/test/snapshot.spec.js.map +1 -0
- package/lib/components/ImageSet/index.js +1 -1
- package/lib/components/ImageSet/index.js.map +1 -1
- package/lib/components/LiveBlogPost/client/index.d.ts +4 -0
- package/lib/components/LiveBlogPost/client/index.js +19 -0
- package/lib/components/LiveBlogPost/client/index.js.map +1 -0
- package/lib/components/LiveBlogPost/index.js +9 -21
- package/lib/components/LiveBlogPost/index.js.map +1 -1
- package/lib/components/LiveBlogWrapper/index.js +1 -1
- package/lib/components/LiveBlogWrapper/index.js.map +1 -1
- package/lib/components/Recommended/index.js +1 -1
- package/lib/components/Recommended/index.js.map +1 -1
- package/lib/components/RichText/index.d.ts +1 -1
- package/lib/components/Table/index.js +1 -1
- package/lib/components/Table/index.js.map +1 -1
- package/lib/components/Video/index.js +1 -1
- package/lib/components/Video/index.js.map +1 -1
- package/lib/components/YoutubeVideo/index.js +1 -1
- package/lib/components/YoutubeVideo/index.js.map +1 -1
- package/lib/extensions/scrollIntoView.d.ts +10 -0
- package/lib/extensions/scrollIntoView.js +32 -0
- package/lib/extensions/scrollIntoView.js.map +1 -0
- package/lib/stories/Clip.stories.d.ts +2 -1
- package/lib/stories/Clip.stories.js +5 -5
- package/lib/stories/Clip.stories.js.map +1 -1
- package/lib/stories/Expander.stories.d.ts +54 -0
- package/lib/stories/Expander.stories.js +142 -0
- package/lib/stories/Expander.stories.js.map +1 -0
- package/package.json +2 -5
- package/src/components/BackToTopButton/client/index.tsx +8 -1
- package/src/components/Body/__snapshots__/index.test.tsx.snap +55 -5
- package/src/components/Body/index.test.tsx +9 -0
- package/src/components/Clip/client/index.ts +68 -26
- package/src/components/Clip/client/main.scss +27 -12
- package/src/components/Clip/client/progressBar.ts +5 -2
- package/src/components/Clip/components/ClipTag.tsx +0 -1
- package/src/components/Clip/components/Container.tsx +10 -3
- package/src/components/Clip/template/index.ts +0 -1
- package/src/components/Clip/test/__snapshots__/snapshot.spec.tsx.snap +8 -16
- package/src/components/Clip/test/index.spec.ts +33 -7
- package/src/components/Expander/client/index.ts +201 -0
- package/src/components/Expander/client/main.scss +162 -0
- package/src/components/Expander/index.tsx +74 -0
- package/src/components/Expander/test/__snapshots__/snapshot.spec.tsx.snap +221 -0
- package/src/components/Expander/test/client/index.spec.tsx +129 -0
- package/src/components/Expander/test/index.spec.tsx +77 -0
- package/src/components/Expander/test/snapshot.spec.tsx +73 -0
- package/src/components/ImageSet/index.tsx +1 -0
- package/src/components/LiveBlogPost/client/index.ts +16 -0
- package/src/components/LiveBlogPost/index.tsx +29 -43
- package/src/components/LiveBlogWrapper/index.tsx +1 -0
- package/src/components/Recommended/index.tsx +1 -0
- package/src/components/Table/index.tsx +1 -0
- package/src/components/Video/index.tsx +4 -1
- package/src/components/YoutubeVideo/index.tsx +4 -1
- package/src/extensions/scrollIntoView.ts +38 -0
- package/src/stories/Clip.stories.tsx +3 -2
- package/src/stories/Expander.stories.scss +3 -0
- package/src/stories/Expander.stories.tsx +159 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.OnlyMobileServer = exports.OnlyMobileWithClient = exports.WithClient = exports.OnlyServer = void 0;
|
|
30
|
+
const Expander_1 = require("../components/Expander");
|
|
31
|
+
const client_1 = require("../components/Expander/client");
|
|
32
|
+
const react_1 = __importStar(require("react"));
|
|
33
|
+
const main_1 = __importDefault(require("@financial-times/o-tracking/main"));
|
|
34
|
+
require("./Expander.stories.scss");
|
|
35
|
+
const client_2 = __importDefault(require("../components/Clip/client"));
|
|
36
|
+
require("./Clip.stories.scss");
|
|
37
|
+
const RichText_1 = __importDefault(require("../components/RichText"));
|
|
38
|
+
const structuredContent = {
|
|
39
|
+
type: 'body',
|
|
40
|
+
version: 1,
|
|
41
|
+
children: [
|
|
42
|
+
{
|
|
43
|
+
type: 'paragraph',
|
|
44
|
+
children: [
|
|
45
|
+
{
|
|
46
|
+
type: 'text',
|
|
47
|
+
value: 'Mike Johnson has survived an attempt to oust him as speaker of the House of Representatives by Marjorie Taylor Greene, a hardline Republican congresswoman from Georgia. ',
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'paragraph',
|
|
53
|
+
children: [
|
|
54
|
+
{
|
|
55
|
+
type: 'text',
|
|
56
|
+
value: 'In a vote on Wednesday night, the lower chamber of Congress rejected Greene’s bid with overwhelming support from Democrats as well as Republicans. ',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
,
|
|
61
|
+
{
|
|
62
|
+
type: 'paragraph',
|
|
63
|
+
children: [
|
|
64
|
+
{
|
|
65
|
+
type: 'text',
|
|
66
|
+
value: 'The vote all but ensures that Johnson will remain in his post until after the November election, and will put a lid on a debate over his political future that has lasted for weeks among Republicans in Congress. ',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: 'clip-set',
|
|
72
|
+
id: 'http://api.ft.com/content/23a00095-d9fc-4cac-ad7c-477e61e3c159',
|
|
73
|
+
autoplay: false,
|
|
74
|
+
loop: false,
|
|
75
|
+
muted: false,
|
|
76
|
+
dataLayout: 'in-line',
|
|
77
|
+
data: {
|
|
78
|
+
referenceIndex: 3,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
const storyArgs = {
|
|
84
|
+
expandLabel: 'Open',
|
|
85
|
+
collapseLabel: 'Close',
|
|
86
|
+
onlyMobile: false,
|
|
87
|
+
id: '111232323-12123-2323',
|
|
88
|
+
};
|
|
89
|
+
exports.default = {
|
|
90
|
+
title: 'Expander',
|
|
91
|
+
component: Expander_1.ExpanderServer,
|
|
92
|
+
tags: ['autodocs'],
|
|
93
|
+
};
|
|
94
|
+
const LiveBLogWrapper = (args) => {
|
|
95
|
+
const { classNames } = args;
|
|
96
|
+
return (react_1.default.createElement("div", { className: classNames },
|
|
97
|
+
react_1.default.createElement("article", { id: "site-content", role: "main", className: "article article-grid article-grid--no-full-width-graphics js enhanced", "data-article-type": "no-full-width-graphics" },
|
|
98
|
+
react_1.default.createElement("div", { className: "article__content", "data-trackable": "article-body", "data-component": "article-body", style: { position: 'relative' } },
|
|
99
|
+
react_1.default.createElement("div", { className: "article__content-body n-content-body js-article__content-body", "data-attribute": "article-content-body" },
|
|
100
|
+
react_1.default.createElement(LiveBlogPostWrapper, { ...args, id: "111" }))),
|
|
101
|
+
react_1.default.createElement("div", { className: "article__right " }))));
|
|
102
|
+
};
|
|
103
|
+
const LiveBlogPostWrapper = (args) => {
|
|
104
|
+
(0, react_1.useEffect)(() => {
|
|
105
|
+
main_1.default.init({
|
|
106
|
+
context: { product: 'next' },
|
|
107
|
+
test: true,
|
|
108
|
+
});
|
|
109
|
+
const clips = client_2.default.init(null, {});
|
|
110
|
+
return () => {
|
|
111
|
+
clips.forEach((clip) => clip.unload());
|
|
112
|
+
};
|
|
113
|
+
}, []);
|
|
114
|
+
return (react_1.default.createElement("article", { id: args.id },
|
|
115
|
+
react_1.default.createElement("div", { className: "n-content-body" },
|
|
116
|
+
react_1.default.createElement("div", { "data-trackable": "truncated-post", "data-trackable-context-post": "1234", "data-component": "example-boundary" },
|
|
117
|
+
react_1.default.createElement(Expander_1.ExpanderServer, { ...args, id: `${args.id}_expander` },
|
|
118
|
+
react_1.default.createElement(RichText_1.default, { structuredContent: { tree: structuredContent } }))))));
|
|
119
|
+
};
|
|
120
|
+
const OnlyServer = (args) => {
|
|
121
|
+
return react_1.default.createElement(LiveBLogWrapper, { ...args });
|
|
122
|
+
};
|
|
123
|
+
exports.OnlyServer = OnlyServer;
|
|
124
|
+
exports.OnlyServer.args = { ...storyArgs };
|
|
125
|
+
const WithClient = (args) => {
|
|
126
|
+
(0, react_1.useEffect)(() => {
|
|
127
|
+
const clips = client_2.default.init(null, {});
|
|
128
|
+
const expanders = client_1.ExpanderClient.init();
|
|
129
|
+
return () => {
|
|
130
|
+
clips.forEach((clip) => clip.unload());
|
|
131
|
+
expanders.forEach((expander) => expander?.destroy());
|
|
132
|
+
};
|
|
133
|
+
}, []);
|
|
134
|
+
return react_1.default.createElement(LiveBLogWrapper, { ...args });
|
|
135
|
+
};
|
|
136
|
+
exports.WithClient = WithClient;
|
|
137
|
+
exports.WithClient.args = { ...storyArgs };
|
|
138
|
+
exports.OnlyMobileWithClient = exports.WithClient;
|
|
139
|
+
exports.OnlyMobileWithClient.args = { ...storyArgs, onlyMobile: true };
|
|
140
|
+
exports.OnlyMobileServer = exports.OnlyServer;
|
|
141
|
+
exports.OnlyMobileServer.args = { ...storyArgs, onlyMobile: true };
|
|
142
|
+
//# sourceMappingURL=Expander.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Expander.stories.js","sourceRoot":"","sources":["../../src/stories/Expander.stories.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/cp-content-pipeline-ui",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.10.0-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -17,9 +17,6 @@
|
|
|
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.8.0",
|
|
21
|
-
"@financial-times/cp-content-pipeline-schema": "^2.11.0",
|
|
22
|
-
"@financial-times/cp-content-pipeline-styles": "^2.5.2",
|
|
23
20
|
"@financial-times/n-scrollytelling-image": "^1.1.0",
|
|
24
21
|
"@financial-times/o-colors": "^6.6.2",
|
|
25
22
|
"@financial-times/o-grid": "^6.1.5",
|
|
@@ -61,7 +58,7 @@
|
|
|
61
58
|
"@financial-times/o-loading": "^5.2.3",
|
|
62
59
|
"@financial-times/o-teaser": "^6.2.2",
|
|
63
60
|
"@financial-times/x-teaser": "^14.6.5",
|
|
64
|
-
"classnames": "^2.
|
|
61
|
+
"classnames": "^2.5.1"
|
|
65
62
|
},
|
|
66
63
|
"peerDependencies": {
|
|
67
64
|
"@financial-times/x-interaction": ">=14",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
//To know when scroll event was triggered by scrollIntoView, it needs to polyfill scrollIntoView method
|
|
2
|
+
import '../../../extensions/scrollIntoView'
|
|
1
3
|
import React, { useState, useEffect, useRef } from 'react'
|
|
2
4
|
import { throttle } from './utils'
|
|
3
5
|
|
|
@@ -51,7 +53,12 @@ export default function BackToTop({
|
|
|
51
53
|
const hasPassedTriggerPosition = startElement
|
|
52
54
|
? startElement?.getBoundingClientRect()?.bottom <= 0
|
|
53
55
|
: (element?.current?.getBoundingClientRect()?.top ?? 0) <= 0 // Add a fallback value of 0 if element is undefined
|
|
54
|
-
if
|
|
56
|
+
// if the user has scrolled past the trigger element and the scroll is not programatic
|
|
57
|
+
const window =
|
|
58
|
+
((scrollableElement as HTMLElement)?.ownerDocument
|
|
59
|
+
?.defaultView as Window & { programmaticScroll?: boolean }) ||
|
|
60
|
+
(scrollableElement as Window & { programmaticScroll?: boolean })
|
|
61
|
+
if (hasPassedTriggerPosition && !window?.programmaticScroll) {
|
|
55
62
|
result = true
|
|
56
63
|
}
|
|
57
64
|
}
|
|
@@ -145,6 +145,7 @@ exports[`Body default renderers renders default renderer for LiveBlogPackage 1`]
|
|
|
145
145
|
<DocumentFragment>
|
|
146
146
|
<div
|
|
147
147
|
class="x-live-blog-wrapper"
|
|
148
|
+
data-component="live-blog-wrapper"
|
|
148
149
|
data-live-blog-wrapper-id="live-blog-wrapper"
|
|
149
150
|
>
|
|
150
151
|
<article
|
|
@@ -172,7 +173,7 @@ exports[`Body default renderers renders default renderer for LiveBlogPackage 1`]
|
|
|
172
173
|
<time
|
|
173
174
|
class="o-date x-live-blog-post__timestamp"
|
|
174
175
|
data-o-component="o-date"
|
|
175
|
-
data-o-date-format="
|
|
176
|
+
data-o-date-format="MMM dd, HH:mm"
|
|
176
177
|
data-o-date-text-case="sentence"
|
|
177
178
|
datetime="2024-06-11T14:13:25.527Z"
|
|
178
179
|
itemprop="datePublished"
|
|
@@ -180,7 +181,7 @@ exports[`Body default renderers renders default renderer for LiveBlogPackage 1`]
|
|
|
180
181
|
<span
|
|
181
182
|
data-o-date-printer="true"
|
|
182
183
|
>
|
|
183
|
-
|
|
184
|
+
11/06/2024, 14:13:25
|
|
184
185
|
</span>
|
|
185
186
|
</time>
|
|
186
187
|
</span>
|
|
@@ -202,10 +203,59 @@ exports[`Body default renderers renders default renderer for LiveBlogPackage 1`]
|
|
|
202
203
|
</h2>
|
|
203
204
|
<div
|
|
204
205
|
class="x-live-blog-post__body n-content-body article--body"
|
|
206
|
+
data-trackable="truncated-post"
|
|
207
|
+
data-trackable-category="live-blog"
|
|
208
|
+
data-trackable-context-post="00000000-0000-0000-0000-000000000000"
|
|
205
209
|
>
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
<div
|
|
211
|
+
class="cp-expander cp-expander--mobile-only cp-expander--not-initialised"
|
|
212
|
+
data-component="expander"
|
|
213
|
+
data-state="collapsed"
|
|
214
|
+
id="truncated-00000000-0000-0000-0000-000000000000__container"
|
|
215
|
+
>
|
|
216
|
+
<div
|
|
217
|
+
class="cp-expander-content"
|
|
218
|
+
id="truncated-00000000-0000-0000-0000-000000000000"
|
|
219
|
+
>
|
|
220
|
+
<div
|
|
221
|
+
class="cp-expander__expand"
|
|
222
|
+
>
|
|
223
|
+
<a
|
|
224
|
+
aria-controls="truncated-00000000-0000-0000-0000-000000000000"
|
|
225
|
+
aria-expanded="false"
|
|
226
|
+
aria-hidden="false"
|
|
227
|
+
class="cp-expander__link"
|
|
228
|
+
data-action="expand"
|
|
229
|
+
data-trackable="truncated-post"
|
|
230
|
+
data-trackable-context-truncated-id="truncated-00000000-0000-0000-0000-000000000000"
|
|
231
|
+
data-trackable-context-truncated-post="expand"
|
|
232
|
+
href="#truncated-00000000-0000-0000-0000-000000000000"
|
|
233
|
+
>
|
|
234
|
+
Expand post
|
|
235
|
+
</a>
|
|
236
|
+
</div>
|
|
237
|
+
<p>
|
|
238
|
+
Lorem ipsum dolor sit amet
|
|
239
|
+
</p>
|
|
240
|
+
<div
|
|
241
|
+
class="cp-expander__collapse"
|
|
242
|
+
>
|
|
243
|
+
<a
|
|
244
|
+
aria-controls="truncated-00000000-0000-0000-0000-000000000000"
|
|
245
|
+
aria-expanded="false"
|
|
246
|
+
aria-hidden="true"
|
|
247
|
+
class="cp-expander__link"
|
|
248
|
+
data-action="collapse"
|
|
249
|
+
data-trackable="truncated-post"
|
|
250
|
+
data-trackable-context-truncated-id="truncated-00000000-0000-0000-0000-000000000000"
|
|
251
|
+
data-trackable-context-truncated-post="collapse"
|
|
252
|
+
href="#truncated-00000000-0000-0000-0000-000000000000__container"
|
|
253
|
+
>
|
|
254
|
+
Collapse post
|
|
255
|
+
</a>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
209
259
|
</div>
|
|
210
260
|
<div
|
|
211
261
|
class="x-live-blog-post__controls"
|
|
@@ -103,6 +103,15 @@ const legacyOverridesToTest: [
|
|
|
103
103
|
]
|
|
104
104
|
|
|
105
105
|
describe('Body', () => {
|
|
106
|
+
let mockDate: jest.SpyInstance
|
|
107
|
+
beforeAll(() => {
|
|
108
|
+
mockDate = jest
|
|
109
|
+
.spyOn(Date.prototype, 'toLocaleString')
|
|
110
|
+
.mockReturnValue('11/06/2024, 14:13:25')
|
|
111
|
+
})
|
|
112
|
+
afterAll(() => {
|
|
113
|
+
mockDate.mockRestore()
|
|
114
|
+
})
|
|
106
115
|
describe('default renderers', () => {
|
|
107
116
|
test.each(typesToTest)('renders default renderer for %s', (type) => {
|
|
108
117
|
const { asFragment } = render(
|
|
@@ -134,6 +134,7 @@ class Clip extends ClipInterface {
|
|
|
134
134
|
private lastTimeUpdate: number | null = null
|
|
135
135
|
private muteIcon: HTMLElement | null = null
|
|
136
136
|
private controls: HTMLElement | null = null
|
|
137
|
+
private playPauseButton: HTMLElement | null = null
|
|
137
138
|
private bottomBar: HTMLElement | null = null
|
|
138
139
|
private playText: HTMLElement | null = null
|
|
139
140
|
private progressBar: ProgressBar | null = null
|
|
@@ -516,27 +517,42 @@ class Clip extends ClipInterface {
|
|
|
516
517
|
this.muteIcon.addEventListener('click', () => {
|
|
517
518
|
this.muted = !this.muted
|
|
518
519
|
})
|
|
520
|
+
// this will ensure that the controls can fade out for mouse-based users
|
|
521
|
+
this.muteIcon.onmouseup = () => {
|
|
522
|
+
this.muteIcon?.blur()
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
const playPauseButton = document.createElement('button')
|
|
526
|
+
playPauseButton.setAttribute('type', 'button')
|
|
527
|
+
this.playPauseButton = playPauseButton
|
|
528
|
+
this.togglePlayPauseButton()
|
|
519
529
|
|
|
520
|
-
const pauseIcon = document.createElement('button')
|
|
521
530
|
if (this.opts.loop) {
|
|
531
|
+
playPauseButton.classList.add('cp-clip__playpause-icon-autoplay')
|
|
522
532
|
customControls.classList.add('cp-clip__video-mode-autoplay')
|
|
523
|
-
pauseIcon.classList.add('cp-clip__pause-icon-autoplay')
|
|
524
|
-
pauseIcon.setAttribute('tabindex', '-1')
|
|
525
|
-
pauseIcon.setAttribute('data-trackable', 'video-clip-pause')
|
|
526
|
-
pauseIcon.setAttribute('aria-label', 'Pause')
|
|
527
533
|
const progressRing = document.createElement('div')
|
|
528
|
-
progressRing.classList.add('cp-
|
|
529
|
-
|
|
534
|
+
progressRing.classList.add('cp-clip__playpause-icon-autoplay-progress')
|
|
535
|
+
playPauseButton.appendChild(progressRing)
|
|
530
536
|
this.progressRing = progressRing
|
|
531
537
|
} else {
|
|
532
|
-
|
|
533
|
-
pauseIcon.setAttribute('aria-label', 'Pause')
|
|
534
|
-
pauseIcon.setAttribute('data-trackable', 'video-clip-pause')
|
|
535
|
-
pauseIcon.setAttribute('tabindex', '-1')
|
|
538
|
+
playPauseButton.classList.add('cp-clip__playpause-icon')
|
|
536
539
|
this.progressBar = this.createProgressBar()
|
|
540
|
+
// if we have a progress bar then we have the ability to step back and forward, so permit focussing on the video
|
|
541
|
+
video.setAttribute('tabIndex', '0')
|
|
542
|
+
video.setAttribute(
|
|
543
|
+
'aria-label',
|
|
544
|
+
'Video clip: use left and right arrow keys to skip backward or forwards'
|
|
545
|
+
)
|
|
537
546
|
}
|
|
538
547
|
|
|
539
|
-
|
|
548
|
+
playPauseButton.onclick = () => {
|
|
549
|
+
this.togglePlay()
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// this will ensure that the controls can fade out for mouse-based users
|
|
553
|
+
playPauseButton.onmouseup = () => {
|
|
554
|
+
playPauseButton.blur()
|
|
555
|
+
}
|
|
540
556
|
|
|
541
557
|
const noAudioIcon = this.createNoAudioIcon()
|
|
542
558
|
|
|
@@ -560,7 +576,7 @@ class Clip extends ClipInterface {
|
|
|
560
576
|
bottomBar.append(closedCaptionIcon)
|
|
561
577
|
}
|
|
562
578
|
|
|
563
|
-
bottomBar.append(
|
|
579
|
+
bottomBar.append(playPauseButton)
|
|
564
580
|
bottomBar.append(this.videoHasNoAudio() ? noAudioIcon : muteIcon)
|
|
565
581
|
customControls.prepend(playIconContainer)
|
|
566
582
|
customControls.append(bottomBar)
|
|
@@ -575,15 +591,24 @@ class Clip extends ClipInterface {
|
|
|
575
591
|
video.addEventListener('playing', () => {
|
|
576
592
|
//resize controls in case poster is different size than video at the end
|
|
577
593
|
this.resizeControls()
|
|
578
|
-
|
|
594
|
+
this.togglePlayPauseButton()
|
|
595
|
+
this.containerEl.classList.remove(
|
|
596
|
+
'cp-clip--paused',
|
|
597
|
+
'cp-clip--loading',
|
|
598
|
+
'cp-clip--ready'
|
|
599
|
+
)
|
|
579
600
|
this.containerEl.classList.add('cp-clip--playing')
|
|
580
|
-
this.containerEl.classList.remove('cp-clip--loading')
|
|
581
601
|
this.fadeOut()
|
|
582
602
|
})
|
|
583
603
|
|
|
584
604
|
video.addEventListener('pause', () => {
|
|
585
|
-
this.
|
|
586
|
-
this.containerEl.classList.remove(
|
|
605
|
+
this.togglePlayPauseButton()
|
|
606
|
+
this.containerEl.classList.remove(
|
|
607
|
+
'cp-clip--playing',
|
|
608
|
+
'cp-clip--loading',
|
|
609
|
+
'cp-clip--ready'
|
|
610
|
+
)
|
|
611
|
+
this.containerEl.classList.add('cp-clip--paused')
|
|
587
612
|
playIcon.setAttribute('data-trackable', 'video-clip-resume')
|
|
588
613
|
|
|
589
614
|
this.fadeIn()
|
|
@@ -630,6 +655,7 @@ class Clip extends ClipInterface {
|
|
|
630
655
|
this.playText.innerText = `PLAY | ${duration}`
|
|
631
656
|
this.playText.classList.add('cp-clip__play-text')
|
|
632
657
|
playIconContainer.append(this.playText)
|
|
658
|
+
this.containerEl.classList.add('cp-clip--ready')
|
|
633
659
|
}
|
|
634
660
|
|
|
635
661
|
if (video.readyState >= 1) {
|
|
@@ -1051,14 +1077,7 @@ class Clip extends ClipInterface {
|
|
|
1051
1077
|
const hasFocus = this.isFocused()
|
|
1052
1078
|
const isPlaying = this.isVideoPlaying()
|
|
1053
1079
|
if (!hasFocus) return
|
|
1054
|
-
if (event.
|
|
1055
|
-
// The default action from pressing the spacebar is to scroll down the page
|
|
1056
|
-
// We prevent the page from scrolling down if the video is in view and someone presses the space bar
|
|
1057
|
-
event.preventDefault()
|
|
1058
|
-
event.stopImmediatePropagation()
|
|
1059
|
-
const currentElement: HTMLElement = document.activeElement as HTMLElement
|
|
1060
|
-
if (currentElement === this.videoEl) this.togglePlay()
|
|
1061
|
-
} else if (isPlaying && event.key === 'ArrowLeft') {
|
|
1080
|
+
if (isPlaying && event.key === 'ArrowLeft') {
|
|
1062
1081
|
this.progressBar?.stepBackward()
|
|
1063
1082
|
event.preventDefault()
|
|
1064
1083
|
event.stopImmediatePropagation()
|
|
@@ -1087,7 +1106,30 @@ class Clip extends ClipInterface {
|
|
|
1087
1106
|
this.videoEl.play()
|
|
1088
1107
|
}
|
|
1089
1108
|
this.videoEl.classList.add('no-focus-style')
|
|
1090
|
-
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
togglePlayPauseButton() {
|
|
1112
|
+
if (!this.playPauseButton) return
|
|
1113
|
+
|
|
1114
|
+
const isPlaying = this.isVideoPlaying()
|
|
1115
|
+
|
|
1116
|
+
this.playPauseButton.classList.toggle(
|
|
1117
|
+
'cp-clip__playpause-icon-pause',
|
|
1118
|
+
isPlaying
|
|
1119
|
+
)
|
|
1120
|
+
this.playPauseButton.classList.toggle(
|
|
1121
|
+
'cp-clip__playpause-icon-play',
|
|
1122
|
+
!isPlaying
|
|
1123
|
+
)
|
|
1124
|
+
|
|
1125
|
+
this.playPauseButton.setAttribute(
|
|
1126
|
+
'aria-label',
|
|
1127
|
+
isPlaying ? 'Pause' : 'Play'
|
|
1128
|
+
)
|
|
1129
|
+
this.playPauseButton.setAttribute(
|
|
1130
|
+
'data-trackable',
|
|
1131
|
+
isPlaying ? 'video-clip-pause' : 'video-clip-play'
|
|
1132
|
+
)
|
|
1091
1133
|
}
|
|
1092
1134
|
|
|
1093
1135
|
createProgressBar(): ProgressBar {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.cp-clip__video-controls-bottom-bar {
|
|
53
|
-
display:
|
|
53
|
+
display: flex;
|
|
54
54
|
width: 100%;
|
|
55
55
|
height: 35%;
|
|
56
56
|
bottom: 0px;
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
}
|
|
65
65
|
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3) 38.38%, rgba(153, 153, 153, 0) 100%);
|
|
66
66
|
|
|
67
|
-
&--fade-out {
|
|
67
|
+
&--fade-out:not(:has(button:focus)) {
|
|
68
68
|
@include fade-out-animation();
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -121,9 +121,21 @@
|
|
|
121
121
|
background-position: 50%;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
&.cp-clip--
|
|
124
|
+
&.cp-clip--ready .cp-clip__video-controls-bottom-bar:not(:has(button:focus)),
|
|
125
|
+
&.cp-clip--paused .cp-clip__video-controls-bottom-bar:not(:has(button:focus)) {
|
|
126
|
+
@include fade-out-animation();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// do not show the large play button when any of these are true:
|
|
130
|
+
// if the video is playing
|
|
131
|
+
// if the video is loading
|
|
132
|
+
// if the bottom bar area has a focussed button
|
|
133
|
+
&.cp-clip--playing .cp-clip__play-icon-container,
|
|
134
|
+
&.cp-clip--loading .cp-clip__play-icon-container,
|
|
135
|
+
.cp-clip__video-controls:has(.cp-clip__video-controls-bottom-bar button:focus) .cp-clip__play-icon-container {
|
|
125
136
|
display: none;
|
|
126
137
|
}
|
|
138
|
+
|
|
127
139
|
&.cp-clip--playing .cp-clip__video-controls-bottom-bar {
|
|
128
140
|
display: flex;
|
|
129
141
|
}
|
|
@@ -132,27 +144,30 @@
|
|
|
132
144
|
display: block;
|
|
133
145
|
}
|
|
134
146
|
|
|
135
|
-
|
|
136
|
-
|
|
147
|
+
.cp-clip__playpause-icon-pause {
|
|
148
|
+
// The icon will be cached in the FT-App
|
|
149
|
+
// See: https://github.com/Financial-Times/ft-app/blob/main/tools/webpack/client/webpack.config.common.js#L218
|
|
150
|
+
@include oIconsContent($icon-name: 'pause', $size: 32px, $color: oColorsByName('white'));
|
|
137
151
|
}
|
|
138
152
|
|
|
139
|
-
.cp-
|
|
153
|
+
.cp-clip__playpause-icon-play {
|
|
140
154
|
// The icon will be cached in the FT-App
|
|
141
155
|
// See: https://github.com/Financial-Times/ft-app/blob/main/tools/webpack/client/webpack.config.common.js#L218
|
|
142
|
-
@include oIconsContent($icon-name: '
|
|
143
|
-
border: none;
|
|
156
|
+
@include oIconsContent($icon-name: 'play', $size: 32px, $color: oColorsByName('white'));
|
|
144
157
|
}
|
|
145
158
|
|
|
159
|
+
.cp-clip__playpause-icon {
|
|
160
|
+
border: none;
|
|
161
|
+
}
|
|
146
162
|
|
|
147
|
-
.cp-
|
|
148
|
-
@include oIconsContent($icon-name: 'pause', $size: 32px, $color: oColorsByName('white'));
|
|
163
|
+
.cp-clip__playpause-icon-autoplay {
|
|
149
164
|
border-radius: 50%;
|
|
150
165
|
border: 2px solid oColorsByName('ft-grey');
|
|
151
166
|
padding:0px;
|
|
152
167
|
margin-left:oSpacingByName('s2');
|
|
153
168
|
}
|
|
154
169
|
|
|
155
|
-
.cp-
|
|
170
|
+
.cp-clip__playpause-icon-autoplay-progress {
|
|
156
171
|
width: 100%;
|
|
157
172
|
height: 100%;
|
|
158
173
|
border-radius: 50%;
|
|
@@ -198,7 +213,7 @@
|
|
|
198
213
|
@include oIconsContent($icon-name: 'closed-captions-on', $size: 32px, $color: oColorsByName('white'));
|
|
199
214
|
}
|
|
200
215
|
|
|
201
|
-
.cp-clip--fade-out {
|
|
216
|
+
.cp-clip--fade-out:not(:has(button:focus)) {
|
|
202
217
|
@include fade-out-animation();
|
|
203
218
|
}
|
|
204
219
|
|
|
@@ -68,7 +68,7 @@ class ProgressBar {
|
|
|
68
68
|
}
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
const touchEnd = (e: TouchEvent) => {
|
|
72
72
|
this.touchStarted = false
|
|
73
73
|
this.timeoutPressed = window.setTimeout(() => {
|
|
74
74
|
mainBar.classList.remove('cp-clip__progress-enlarged')
|
|
@@ -77,7 +77,10 @@ class ProgressBar {
|
|
|
77
77
|
this.scrub(e.changedTouches[0].clientX)
|
|
78
78
|
}
|
|
79
79
|
e.preventDefault()
|
|
80
|
-
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
container.addEventListener('touchend', touchEnd)
|
|
83
|
+
container.addEventListener('touchcancel', touchEnd)
|
|
81
84
|
|
|
82
85
|
container.addEventListener('touchmove', (e) => {
|
|
83
86
|
if (e.changedTouches[0]) {
|
|
@@ -7,9 +7,11 @@ interface ContainerProps {
|
|
|
7
7
|
|
|
8
8
|
export const Container = ({ dataLayout, children }: ContainerProps) => {
|
|
9
9
|
return dataLayout === 'full-grid' ? (
|
|
10
|
-
<div className="n-content-layout__container">
|
|
10
|
+
<div className="n-content-layout__container" data-component="clip-set">
|
|
11
|
+
{children}
|
|
12
|
+
</div>
|
|
11
13
|
) : dataLayout === 'mid-grid' ? (
|
|
12
|
-
<div className="n-content-layout__container">
|
|
14
|
+
<div className="n-content-layout__container" data-component="clip-set">
|
|
13
15
|
<div
|
|
14
16
|
data-o-grid-colspan="12 S12 M12 L10 XL10"
|
|
15
17
|
className="n-content-layout__container--mid-grid"
|
|
@@ -18,6 +20,11 @@ export const Container = ({ dataLayout, children }: ContainerProps) => {
|
|
|
18
20
|
</div>
|
|
19
21
|
</div>
|
|
20
22
|
) : (
|
|
21
|
-
<div
|
|
23
|
+
<div
|
|
24
|
+
className="n-content-layout__container--in-line"
|
|
25
|
+
data-component="clip-set"
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</div>
|
|
22
29
|
)
|
|
23
30
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// This file will is used by next-es-interface and it renders the component as a string
|
|
2
|
-
/* eslint-disable import/no-unused-modules */
|
|
3
2
|
// TODO: Remove this file once next-es-interface and Elastic Search won't be used anymore to render articles (After r13n API will be used in Production by all the consumers: FT-App, next-article, FT Edit)
|
|
4
3
|
import React from 'react'
|
|
5
4
|
import ReactDOMServer from 'react-dom/server'
|