@financial-times/cp-content-pipeline-ui 6.13.0 → 6.14.1
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 +23 -0
- package/lib/client.d.ts +1 -0
- package/lib/client.js +3 -1
- package/lib/client.js.map +1 -1
- package/lib/components/Flourish/index.js +3 -3
- package/lib/components/Flourish/index.js.map +1 -1
- package/lib/components/RichText/index.d.ts +1 -1
- package/lib/components/RichText/index.test.js +6 -6
- package/lib/components/RichText/index.test.js.map +1 -1
- package/lib/components/Topper/client/index.d.ts +2 -0
- package/lib/components/Topper/client/index.js +6 -0
- package/lib/components/Topper/client/index.js.map +1 -0
- package/lib/components/Topper/client/tracking.d.ts +17 -0
- package/lib/components/Topper/client/tracking.js +68 -0
- package/lib/components/Topper/client/tracking.js.map +1 -0
- package/lib/components/Topper/client/tracking.spec.d.ts +1 -0
- package/lib/components/Topper/client/tracking.spec.js +115 -0
- package/lib/components/Topper/client/tracking.spec.js.map +1 -0
- package/package.json +2 -2
- package/src/client.ts +1 -0
- package/src/components/Flourish/index.tsx +5 -2
- package/src/components/Flourish/test/__snapshots__/snapshot.spec.tsx.snap +12 -0
- package/src/components/RichText/index.test.tsx +14 -13
- package/src/components/Topper/client/index.ts +3 -0
- package/src/components/Topper/client/tracking.spec.ts +132 -0
- package/src/components/Topper/client/tracking.ts +88 -0
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -574,6 +574,29 @@
|
|
|
574
574
|
* @financial-times/cp-content-pipeline-client bumped from ^3.7.2 to ^3.7.3
|
|
575
575
|
* @financial-times/cp-content-pipeline-schema bumped from ^2.10.1 to ^2.10.2
|
|
576
576
|
|
|
577
|
+
## [6.14.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v6.14.0...cp-content-pipeline-ui-v6.14.1) (2024-07-16)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
### Bug Fixes
|
|
581
|
+
|
|
582
|
+
* update list-item and block-quote tag mapping to accept paragraphs ([b8b3c4b](https://github.com/Financial-Times/cp-content-pipeline/commit/b8b3c4bc59e22335b8c7b9adbd33365d7c050c19))
|
|
583
|
+
* use Content Tree transit namespace in tagMappings ([06b6080](https://github.com/Financial-Times/cp-content-pipeline/commit/06b60806e2dc0efb66a419cd87f3a40ccccf357a))
|
|
584
|
+
|
|
585
|
+
## [6.14.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v6.13.0...cp-content-pipeline-ui-v6.14.0) (2024-07-16)
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
### Features
|
|
589
|
+
|
|
590
|
+
* tracking for flourish toppers ([4c19db6](https://github.com/Financial-Times/cp-content-pipeline/commit/4c19db61bf28e3a2f04c6eae8eb7344711076ea6))
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
### Bug Fixes
|
|
594
|
+
|
|
595
|
+
* decrease amount of element needed to be seen ([ba8264a](https://github.com/Financial-Times/cp-content-pipeline/commit/ba8264aa99c75a30db7b878c64766816d1464bdc))
|
|
596
|
+
* genericise class to be used on all toppers ([1021468](https://github.com/Financial-Times/cp-content-pipeline/commit/1021468cfdd6d1f75a1d7a45ec7f7c142da6f9a8))
|
|
597
|
+
* remove unneeded data attribute ([6ce8529](https://github.com/Financial-Times/cp-content-pipeline/commit/6ce8529588984839dccf21d29375450671ad2841))
|
|
598
|
+
* return at first opportunity ([508b07c](https://github.com/Financial-Times/cp-content-pipeline/commit/508b07c7af834b6f2d02d2644ec126da195201e3))
|
|
599
|
+
|
|
577
600
|
## [6.13.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v6.12.0...cp-content-pipeline-ui-v6.13.0) (2024-07-10)
|
|
578
601
|
|
|
579
602
|
|
package/lib/client.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
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
|
+
export { TopperTracker } from './components/Topper/client/index';
|
package/lib/client.js
CHANGED
|
@@ -3,11 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FlourishSSREmbed = exports.BackToTopButton = exports.Clip = void 0;
|
|
6
|
+
exports.TopperTracker = exports.FlourishSSREmbed = exports.BackToTopButton = exports.Clip = void 0;
|
|
7
7
|
var index_1 = require("./components/Clip/client/index");
|
|
8
8
|
Object.defineProperty(exports, "Clip", { enumerable: true, get: function () { return __importDefault(index_1).default; } });
|
|
9
9
|
var client_1 = require("./components/BackToTopButton/client");
|
|
10
10
|
Object.defineProperty(exports, "BackToTopButton", { enumerable: true, get: function () { return __importDefault(client_1).default; } });
|
|
11
11
|
var index_2 = require("./components/Flourish/client/index");
|
|
12
12
|
Object.defineProperty(exports, "FlourishSSREmbed", { enumerable: true, get: function () { return __importDefault(index_2).default; } });
|
|
13
|
+
var index_3 = require("./components/Topper/client/index");
|
|
14
|
+
Object.defineProperty(exports, "TopperTracker", { enumerable: true, get: function () { return index_3.TopperTracker; } });
|
|
13
15
|
//# sourceMappingURL=client.js.map
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgE;AAAvD,8GAAA,OAAO,OAAQ;AACxB,8DAAgF;AAAvE,0HAAA,OAAO,OAAmB;AACnC,4DAAgF;AAAvE,0HAAA,OAAO,OAAoB"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgE;AAAvD,8GAAA,OAAO,OAAQ;AACxB,8DAAgF;AAAvE,0HAAA,OAAO,OAAmB;AACnC,4DAAgF;AAAvE,0HAAA,OAAO,OAAoB;AACpC,0DAAgE;AAAvD,sGAAA,aAAa,OAAA"}
|
|
@@ -10,6 +10,8 @@ const DisclaimerNotice = ({ id }) => (react_1.default.createElement("div", { id:
|
|
|
10
10
|
react_1.default.createElement("div", { className: "o-message__content" },
|
|
11
11
|
react_1.default.createElement("p", { className: "o-message__content-main" }, "You are seeing a snapshot of an interactive graphic. This is most likely due to being offline or JavaScript being disabled in your browser.")))));
|
|
12
12
|
function Flourish({ id, flourishType, description, layoutWidth, fallbackImage, iFrame = false, inArticleBody = true, }) {
|
|
13
|
+
if (!id)
|
|
14
|
+
return null;
|
|
13
15
|
const anchorHref = `#${id}`;
|
|
14
16
|
const fullGrid = layoutWidth === 'full-grid' || layoutWidth === 'grid';
|
|
15
17
|
const figureClassnames = (0, classnames_1.default)({
|
|
@@ -27,13 +29,11 @@ function Flourish({ id, flourishType, description, layoutWidth, fallbackImage, i
|
|
|
27
29
|
aspectRatio: `${fallbackImage.width}/${fallbackImage.height}`,
|
|
28
30
|
}
|
|
29
31
|
: {};
|
|
30
|
-
if (!id)
|
|
31
|
-
return null;
|
|
32
32
|
return (react_1.default.createElement("div", { className: (0, classnames_1.default)({
|
|
33
33
|
'n-content-layout': inArticleBody,
|
|
34
34
|
flourish: iFrame,
|
|
35
35
|
'flourish--iFrame': iFrame,
|
|
36
|
-
}), "data-layout-width": fullGrid ? 'full-grid' : null, "data-component": "flourish" },
|
|
36
|
+
}), "data-layout-width": fullGrid ? 'full-grid' : null, "data-component": "flourish", "data-component-id": id, "data-component-type": inArticleBody ? 'flourish-in-article' : 'flourish-topper' },
|
|
37
37
|
iFrame && (react_1.default.createElement("iframe", { src: `https://flo.uri.sh/visualisation/${id}/embed?hideTitle=${!inArticleBody}`, style: { width: '100%', aspectRatio: iframeAspectRatio }, className: "flourish__i-frame" })),
|
|
38
38
|
react_1.default.createElement("figure", { className: figureClassnames, "data-original-image-width": fullGrid ? fallbackImage?.width : null, "data-original-image-height": fullGrid ? fallbackImage?.height : null },
|
|
39
39
|
react_1.default.createElement("a", { href: anchorHref },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Flourish/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4DAAmC;AAqBnC,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,EAAmB,EAAE,EAAE,CAAC,CACpD,uCACE,EAAE,EAAE,EAAE,EACN,SAAS,EAAC,mEAAmE,sBAC5D,WAAW;IAE5B,uCAAK,SAAS,EAAC,sBAAsB;QACnC,uCAAK,SAAS,EAAC,oBAAoB;YACjC,qCAAG,SAAS,EAAC,yBAAyB,kJAIlC,CACA,CACF,CACF,CACP,CAAA;AACD,SAAwB,QAAQ,CAAC,EAC/B,EAAE,EACF,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,EACb,MAAM,GAAG,KAAK,EACd,aAAa,GAAG,IAAI,GACN;IACd,MAAM,UAAU,GAAG,IAAI,EAAE,EAAE,CAAA;IAC3B,MAAM,QAAQ,GAAG,WAAW,KAAK,WAAW,IAAI,WAAW,KAAK,MAAM,CAAA;IACtE,MAAM,gBAAgB,GAAG,IAAA,oBAAU,EAAC;QAClC,mBAAmB,EAAE,IAAI;QACzB,6BAA6B,EAAE,IAAI;QACnC,yBAAyB,EAAE,QAAQ;QACnC,gBAAgB,EAAE,MAAM;KACzB,CAAC,CAAA;IAEF,MAAM,iBAAiB,GACrB,MAAM,IAAI,aAAa,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM;QACrD,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE;QAClD,CAAC,CAAC,MAAM,CAAA;IAEZ,MAAM,gBAAgB,GACpB,CAAC,aAAa,IAAI,aAAa,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM;QAC7D,CAAC,CAAC;YACE,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,GAAG,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE;SAC9D;QACH,CAAC,CAAC,EAAE,CAAA;IAER,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Flourish/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4DAAmC;AAqBnC,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,EAAmB,EAAE,EAAE,CAAC,CACpD,uCACE,EAAE,EAAE,EAAE,EACN,SAAS,EAAC,mEAAmE,sBAC5D,WAAW;IAE5B,uCAAK,SAAS,EAAC,sBAAsB;QACnC,uCAAK,SAAS,EAAC,oBAAoB;YACjC,qCAAG,SAAS,EAAC,yBAAyB,kJAIlC,CACA,CACF,CACF,CACP,CAAA;AACD,SAAwB,QAAQ,CAAC,EAC/B,EAAE,EACF,YAAY,EACZ,WAAW,EACX,WAAW,EACX,aAAa,EACb,MAAM,GAAG,KAAK,EACd,aAAa,GAAG,IAAI,GACN;IACd,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IACpB,MAAM,UAAU,GAAG,IAAI,EAAE,EAAE,CAAA;IAC3B,MAAM,QAAQ,GAAG,WAAW,KAAK,WAAW,IAAI,WAAW,KAAK,MAAM,CAAA;IACtE,MAAM,gBAAgB,GAAG,IAAA,oBAAU,EAAC;QAClC,mBAAmB,EAAE,IAAI;QACzB,6BAA6B,EAAE,IAAI;QACnC,yBAAyB,EAAE,QAAQ;QACnC,gBAAgB,EAAE,MAAM;KACzB,CAAC,CAAA;IAEF,MAAM,iBAAiB,GACrB,MAAM,IAAI,aAAa,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM;QACrD,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE;QAClD,CAAC,CAAC,MAAM,CAAA;IAEZ,MAAM,gBAAgB,GACpB,CAAC,aAAa,IAAI,aAAa,EAAE,KAAK,IAAI,aAAa,EAAE,MAAM;QAC7D,CAAC,CAAC;YACE,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,GAAG,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,MAAM,EAAE;SAC9D;QACH,CAAC,CAAC,EAAE,CAAA;IAER,OAAO,CACL,uCACE,SAAS,EAAE,IAAA,oBAAU,EAAC;YACpB,kBAAkB,EAAE,aAAa;YACjC,QAAQ,EAAE,MAAM;YAChB,kBAAkB,EAAE,MAAM;SAC3B,CAAC,uBACiB,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,oBACjC,UAAU,uBACN,EAAE,yBAEnB,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,iBAAiB;QAG1D,MAAM,IAAI,CACT,0CACE,GAAG,EAAE,oCAAoC,EAAE,oBAAoB,CAAC,aAAa,EAAE,EAC/E,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,EACxD,SAAS,EAAC,mBAAmB,GACrB,CACX;QACD,0CACE,SAAS,EAAE,gBAAgB,+BACA,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,gCACrC,QAAQ,CAAC,CAAC,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI;YAEnE,qCAAG,IAAI,EAAE,UAAU;gBACjB,8DAGmB,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,sBACrC,EAAE,wBACA,YAAY;oBAEhC,8BAAC,gBAAgB,IAAC,EAAE,EAAE,EAAE,GAAI;oBAC5B,uCACE,GAAG,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,EAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,gBAAgB,GACvB,CACM,CACR,CACG,CACL,CACP,CAAA;AACH,CAAC;AA7ED,2BA6EC"}
|
|
@@ -2,7 +2,7 @@ import React, { JSXElementConstructor } from 'react';
|
|
|
2
2
|
import type { StructuredContentFragment } from '@financial-times/cp-content-pipeline-client';
|
|
3
3
|
import { ContentTreeWorkarounds } from '@financial-times/cp-content-pipeline-schema';
|
|
4
4
|
export type RichTextComponentMapRecord = Partial<Record<ContentTreeWorkarounds.AnyNode['type'] | 'fallback', JSXElementConstructor<any>>>;
|
|
5
|
-
export declare const ComponentsContext: React.Context<Partial<Record<"blockquote" | "body" | "cite" | "link" | "strong" | "table" | "video" | "clip" | "text" | "layout" | "table-caption" | "table-cell" | "table-row" | "list-item" | "heading" | "recommended" | "image-set" | "flourish" | "
|
|
5
|
+
export declare const ComponentsContext: React.Context<Partial<Record<"blockquote" | "body" | "cite" | "link" | "strong" | "table" | "video" | "clip" | "text" | "layout" | "table-caption" | "table-cell" | "table-row" | "list-item" | "heading" | "recommended" | "image-set" | "flourish" | "pullquote" | "table-body" | "table-footer" | "break" | "thematic-break" | "paragraph" | "emphasis" | "strikethrough" | "list" | "custom-code-component" | "root" | "clip-set" | "tweet" | "big-number" | "scrolly-block" | "scrolly-section" | "scrolly-copy" | "scrolly-heading" | "scrolly-image" | "layout-slot" | "layout-image" | "youtube-video" | "main-image" | "raw-image" | "main-image-raw" | "author-link" | "fallback", React.JSXElementConstructor<any>>> | undefined>;
|
|
6
6
|
type WithOptionalProperty<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
|
|
7
7
|
type RichTextProps = {
|
|
8
8
|
structuredContent: WithOptionalProperty<StructuredContentFragment, 'references'>;
|
|
@@ -58,12 +58,12 @@ describe('<RichText />', () => {
|
|
|
58
58
|
version: 1,
|
|
59
59
|
children: [
|
|
60
60
|
{
|
|
61
|
-
type: '
|
|
62
|
-
children: [{ type: 'text', value: 'first
|
|
61
|
+
type: 'paragraph',
|
|
62
|
+
children: [{ type: 'text', value: 'first paragraph' }],
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
|
-
type: '
|
|
66
|
-
children: [{ type: 'text', value: 'second
|
|
65
|
+
type: 'paragraph',
|
|
66
|
+
children: [{ type: 'text', value: 'second paragraph' }],
|
|
67
67
|
},
|
|
68
68
|
],
|
|
69
69
|
};
|
|
@@ -80,7 +80,7 @@ describe('<RichText />', () => {
|
|
|
80
80
|
version: 1,
|
|
81
81
|
children: [
|
|
82
82
|
{
|
|
83
|
-
type: '
|
|
83
|
+
type: 'paragraph',
|
|
84
84
|
children: [{ type: 'text', value: 'i should render' }],
|
|
85
85
|
},
|
|
86
86
|
{
|
|
@@ -95,7 +95,7 @@ describe('<RichText />', () => {
|
|
|
95
95
|
tree,
|
|
96
96
|
};
|
|
97
97
|
const { getByText } = (0, react_2.render)(react_1.default.createElement(_1.default, { structuredContent: structuredContent }));
|
|
98
|
-
expect(getByText('i should render').tagName).toEqual('
|
|
98
|
+
expect(getByText('i should render').tagName).toEqual('P');
|
|
99
99
|
//wrapping component with react-testing-library is a div
|
|
100
100
|
expect(getByText('i should not render').tagName).toEqual('DIV');
|
|
101
101
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/components/RichText/index.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA4C;AAC5C,kDAA+C;AAC/C,yCAAwB;
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/components/RichText/index.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TopperTracker = void 0;
|
|
4
|
+
const tracking_1 = require("./tracking");
|
|
5
|
+
Object.defineProperty(exports, "TopperTracker", { enumerable: true, get: function () { return tracking_1.TopperTracker; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/Topper/client/index.ts"],"names":[],"mappings":";;;AAAA,yCAA0C;AAEjC,8FAFA,wBAAa,OAEA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare class TopperTracker {
|
|
2
|
+
private startTime;
|
|
3
|
+
private totalVisibleTime;
|
|
4
|
+
private timeElapsedSeconds;
|
|
5
|
+
private type;
|
|
6
|
+
private component;
|
|
7
|
+
private id;
|
|
8
|
+
private observer;
|
|
9
|
+
constructor({ type }?: {
|
|
10
|
+
type?: string | undefined;
|
|
11
|
+
});
|
|
12
|
+
init(): void;
|
|
13
|
+
private dispatchEvent;
|
|
14
|
+
private onChange;
|
|
15
|
+
disconnect(): void;
|
|
16
|
+
}
|
|
17
|
+
export { TopperTracker };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TopperTracker = void 0;
|
|
4
|
+
class TopperTracker {
|
|
5
|
+
constructor({ type = 'flourish-topper' } = {}) {
|
|
6
|
+
this.startTime = 0;
|
|
7
|
+
this.totalVisibleTime = 0;
|
|
8
|
+
this.timeElapsedSeconds = null;
|
|
9
|
+
this.type = type;
|
|
10
|
+
this.component = document.querySelector(`[data-component-type="${this.type}"]`);
|
|
11
|
+
this.id = this.component?.getAttribute('data-component-id') || null;
|
|
12
|
+
this.observer = null;
|
|
13
|
+
}
|
|
14
|
+
init() {
|
|
15
|
+
if (!window.IntersectionObserver || !this.component) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
this.dispatchEvent('mount');
|
|
19
|
+
this.observer = new IntersectionObserver(this.onChange.bind(this), {
|
|
20
|
+
threshold: [0.75],
|
|
21
|
+
});
|
|
22
|
+
this.observer.observe(this.component);
|
|
23
|
+
}
|
|
24
|
+
dispatchEvent(action) {
|
|
25
|
+
const component = {
|
|
26
|
+
name: this.type,
|
|
27
|
+
id: this.id,
|
|
28
|
+
};
|
|
29
|
+
if (this.timeElapsedSeconds) {
|
|
30
|
+
component.timeElapsedSeconds = this.timeElapsedSeconds;
|
|
31
|
+
}
|
|
32
|
+
const event = new CustomEvent('oTracking.event', {
|
|
33
|
+
detail: {
|
|
34
|
+
category: 'component',
|
|
35
|
+
action: action,
|
|
36
|
+
component,
|
|
37
|
+
},
|
|
38
|
+
bubbles: true,
|
|
39
|
+
});
|
|
40
|
+
document.body.dispatchEvent(event);
|
|
41
|
+
}
|
|
42
|
+
onChange(changes) {
|
|
43
|
+
changes.forEach((change) => {
|
|
44
|
+
if (change.target !== this.component) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (change.isIntersecting || change.intersectionRatio >= 1) {
|
|
48
|
+
this.dispatchEvent('view');
|
|
49
|
+
this.startTime = performance.now();
|
|
50
|
+
}
|
|
51
|
+
if (!change.isIntersecting || change.intersectionRatio === 0) {
|
|
52
|
+
this.totalVisibleTime = performance.now() - this.startTime;
|
|
53
|
+
this.timeElapsedSeconds = parseFloat((this.totalVisibleTime / 1000).toFixed(2));
|
|
54
|
+
this.dispatchEvent('stop-view');
|
|
55
|
+
this.totalVisibleTime = 0;
|
|
56
|
+
this.timeElapsedSeconds = null;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
disconnect() {
|
|
61
|
+
if (this.observer && this.component) {
|
|
62
|
+
this.observer.unobserve(this.component);
|
|
63
|
+
this.observer.disconnect();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.TopperTracker = TopperTracker;
|
|
68
|
+
//# sourceMappingURL=tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking.js","sourceRoot":"","sources":["../../../../src/components/Topper/client/tracking.ts"],"names":[],"mappings":";;;AAKA,MAAM,aAAa;IASjB,YAAY,EAAE,IAAI,GAAG,iBAAiB,EAAE,GAAG,EAAE;QAC3C,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;QAClB,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAA;QACzB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,aAAa,CACrC,yBAAyB,IAAI,CAAC,IAAI,IAAI,CACvC,CAAA;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,mBAAmB,CAAC,IAAI,IAAI,CAAA;QACnE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YACnD,OAAM;SACP;QAED,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QAE3B,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACjE,SAAS,EAAE,CAAC,IAAI,CAAC;SAClB,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACvC,CAAC;IAEO,aAAa,CAAC,MAAc;QAClC,MAAM,SAAS,GAAc;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;SACZ,CAAA;QACD,IAAI,IAAI,CAAC,kBAAkB,EAAE;YAC3B,SAAS,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAA;SACvD;QACD,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,iBAAiB,EAAE;YAC/C,MAAM,EAAE;gBACN,QAAQ,EAAE,WAAW;gBACrB,MAAM,EAAE,MAAM;gBACd,SAAS;aACV;YACD,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;QACF,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IACpC,CAAC;IAEO,QAAQ,CAAC,OAAoC;QACnD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YACzB,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,SAAS,EAAE;gBACpC,OAAM;aACP;YACD,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,iBAAiB,IAAI,CAAC,EAAE;gBAC1D,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;gBAC1B,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAA;aACnC;YACD,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,iBAAiB,KAAK,CAAC,EAAE;gBAC5D,IAAI,CAAC,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;gBAC1D,IAAI,CAAC,kBAAkB,GAAG,UAAU,CAClC,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAC1C,CAAA;gBACD,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAA;gBAC/B,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAA;gBACzB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAA;aAC/B;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;YACnC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACvC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAA;SAC3B;IACH,CAAC;CACF;AAEQ,sCAAa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_1 = require("./index");
|
|
4
|
+
describe('TopperTracker', () => {
|
|
5
|
+
let mockIntersectionObserver;
|
|
6
|
+
let mockObserve;
|
|
7
|
+
let mockUnobserve;
|
|
8
|
+
let mockDisconnect;
|
|
9
|
+
let mockComponent;
|
|
10
|
+
let dispatchEventSpy;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockObserve = jest.fn();
|
|
13
|
+
mockUnobserve = jest.fn();
|
|
14
|
+
mockDisconnect = jest.fn();
|
|
15
|
+
mockIntersectionObserver = jest.fn(() => {
|
|
16
|
+
return {
|
|
17
|
+
observe: mockObserve,
|
|
18
|
+
unobserve: mockUnobserve,
|
|
19
|
+
disconnect: mockDisconnect,
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
window.IntersectionObserver = mockIntersectionObserver;
|
|
23
|
+
mockComponent = document.createElement('div');
|
|
24
|
+
mockComponent.setAttribute('data-component-type', 'flourish-topper');
|
|
25
|
+
mockComponent.setAttribute('data-component-id', 'test-id');
|
|
26
|
+
document.body.appendChild(mockComponent);
|
|
27
|
+
jest.spyOn(document, 'querySelector').mockReturnValue(mockComponent);
|
|
28
|
+
jest
|
|
29
|
+
.spyOn(performance, 'now')
|
|
30
|
+
.mockImplementationOnce(() => 1)
|
|
31
|
+
.mockImplementationOnce(() => 12344);
|
|
32
|
+
dispatchEventSpy = jest.spyOn(document.body, 'dispatchEvent');
|
|
33
|
+
});
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
jest.clearAllMocks();
|
|
36
|
+
document.body.removeChild(mockComponent);
|
|
37
|
+
});
|
|
38
|
+
it('should initialise and observe the component', () => {
|
|
39
|
+
const tracker = new index_1.TopperTracker();
|
|
40
|
+
tracker.init();
|
|
41
|
+
expect(mockIntersectionObserver).toHaveBeenCalled();
|
|
42
|
+
expect(mockObserve).toHaveBeenCalledWith(mockComponent);
|
|
43
|
+
});
|
|
44
|
+
it('should dispatch a mount event on intialisation', () => {
|
|
45
|
+
const tracker = new index_1.TopperTracker();
|
|
46
|
+
tracker.init();
|
|
47
|
+
const mountEvent = dispatchEventSpy.mock.calls[0][0];
|
|
48
|
+
expect(mountEvent.type).toBe('oTracking.event');
|
|
49
|
+
expect(mountEvent.detail).toEqual({
|
|
50
|
+
category: 'component',
|
|
51
|
+
action: 'mount',
|
|
52
|
+
component: {
|
|
53
|
+
name: 'flourish-topper',
|
|
54
|
+
id: 'test-id',
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
it('should handle component visibility changes', () => {
|
|
59
|
+
const tracker = new index_1.TopperTracker();
|
|
60
|
+
tracker.init();
|
|
61
|
+
const mockChanges = [
|
|
62
|
+
{
|
|
63
|
+
target: mockComponent,
|
|
64
|
+
isIntersecting: true,
|
|
65
|
+
intersectionRatio: 1.0,
|
|
66
|
+
boundingClientRect: {},
|
|
67
|
+
intersectionRect: {},
|
|
68
|
+
rootBounds: null,
|
|
69
|
+
time: 1,
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
tracker['onChange'](mockChanges);
|
|
73
|
+
const viewEvent = dispatchEventSpy.mock.calls[1][0];
|
|
74
|
+
expect(viewEvent.type).toBe('oTracking.event');
|
|
75
|
+
expect(viewEvent.detail).toEqual({
|
|
76
|
+
category: 'component',
|
|
77
|
+
action: 'view',
|
|
78
|
+
component: {
|
|
79
|
+
name: 'flourish-topper',
|
|
80
|
+
id: 'test-id',
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
const mockChangesAfter = [
|
|
84
|
+
{
|
|
85
|
+
target: mockComponent,
|
|
86
|
+
isIntersecting: false,
|
|
87
|
+
intersectionRatio: 0.0,
|
|
88
|
+
boundingClientRect: {},
|
|
89
|
+
intersectionRect: {},
|
|
90
|
+
rootBounds: null,
|
|
91
|
+
time: 12.3444,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
tracker['onChange'](mockChangesAfter);
|
|
95
|
+
const stopViewEvent = dispatchEventSpy.mock.calls[2][0];
|
|
96
|
+
expect(stopViewEvent.type).toBe('oTracking.event');
|
|
97
|
+
expect(stopViewEvent.detail).toEqual({
|
|
98
|
+
category: 'component',
|
|
99
|
+
action: 'stop-view',
|
|
100
|
+
component: {
|
|
101
|
+
name: 'flourish-topper',
|
|
102
|
+
id: 'test-id',
|
|
103
|
+
timeElapsedSeconds: 12.34,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
it('should disconnect the observer', () => {
|
|
108
|
+
const tracker = new index_1.TopperTracker();
|
|
109
|
+
tracker.init();
|
|
110
|
+
tracker.disconnect();
|
|
111
|
+
expect(mockUnobserve).toHaveBeenCalledWith(mockComponent);
|
|
112
|
+
expect(mockDisconnect).toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=tracking.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracking.spec.js","sourceRoot":"","sources":["../../../../src/components/Topper/client/tracking.spec.ts"],"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.14.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
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#abdc26b",
|
|
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",
|
package/src/client.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
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
|
+
export { TopperTracker } from './components/Topper/client/index'
|
|
@@ -46,6 +46,7 @@ export default function Flourish({
|
|
|
46
46
|
iFrame = false,
|
|
47
47
|
inArticleBody = true,
|
|
48
48
|
}: FlourishProps) {
|
|
49
|
+
if (!id) return null
|
|
49
50
|
const anchorHref = `#${id}`
|
|
50
51
|
const fullGrid = layoutWidth === 'full-grid' || layoutWidth === 'grid'
|
|
51
52
|
const figureClassnames = classnames({
|
|
@@ -68,8 +69,6 @@ export default function Flourish({
|
|
|
68
69
|
}
|
|
69
70
|
: {}
|
|
70
71
|
|
|
71
|
-
if (!id) return null
|
|
72
|
-
|
|
73
72
|
return (
|
|
74
73
|
<div
|
|
75
74
|
className={classnames({
|
|
@@ -79,6 +78,10 @@ export default function Flourish({
|
|
|
79
78
|
})}
|
|
80
79
|
data-layout-width={fullGrid ? 'full-grid' : null}
|
|
81
80
|
data-component="flourish"
|
|
81
|
+
data-component-id={id}
|
|
82
|
+
data-component-type={
|
|
83
|
+
inArticleBody ? 'flourish-in-article' : 'flourish-topper'
|
|
84
|
+
}
|
|
82
85
|
>
|
|
83
86
|
{iFrame && (
|
|
84
87
|
<iframe
|
|
@@ -5,6 +5,8 @@ exports[`Flourish component renders ignoring layout different from full-grid 1`]
|
|
|
5
5
|
<div
|
|
6
6
|
class="n-content-layout"
|
|
7
7
|
data-component="flourish"
|
|
8
|
+
data-component-id="123"
|
|
9
|
+
data-component-type="flourish-in-article"
|
|
8
10
|
>
|
|
9
11
|
<figure
|
|
10
12
|
class="n-content-picture n-content-layout__container"
|
|
@@ -52,6 +54,8 @@ exports[`Flourish component renders with a full-grid layout and fallback image 1
|
|
|
52
54
|
<div
|
|
53
55
|
class="n-content-layout"
|
|
54
56
|
data-component="flourish"
|
|
57
|
+
data-component-id="123"
|
|
58
|
+
data-component-type="flourish-in-article"
|
|
55
59
|
data-layout-width="full-grid"
|
|
56
60
|
>
|
|
57
61
|
<figure
|
|
@@ -102,6 +106,8 @@ exports[`Flourish component renders with an iframe rather than using the embed s
|
|
|
102
106
|
<div
|
|
103
107
|
class="n-content-layout flourish flourish--iFrame"
|
|
104
108
|
data-component="flourish"
|
|
109
|
+
data-component-id="123"
|
|
110
|
+
data-component-type="flourish-in-article"
|
|
105
111
|
data-layout-width="full-grid"
|
|
106
112
|
>
|
|
107
113
|
<iframe
|
|
@@ -157,6 +163,8 @@ exports[`Flourish component renders without n-content-layout class for charts no
|
|
|
157
163
|
<div
|
|
158
164
|
class=""
|
|
159
165
|
data-component="flourish"
|
|
166
|
+
data-component-id="123"
|
|
167
|
+
data-component-type="flourish-topper"
|
|
160
168
|
data-layout-width="full-grid"
|
|
161
169
|
>
|
|
162
170
|
<figure
|
|
@@ -208,6 +216,8 @@ exports[`does not set aspect ratios when in article body 1`] = `
|
|
|
208
216
|
<div
|
|
209
217
|
class="n-content-layout"
|
|
210
218
|
data-component="flourish"
|
|
219
|
+
data-component-id="123"
|
|
220
|
+
data-component-type="flourish-in-article"
|
|
211
221
|
data-layout-width="full-grid"
|
|
212
222
|
>
|
|
213
223
|
<figure
|
|
@@ -258,6 +268,8 @@ exports[`sets the hideTitle param in the iframe url to true when not in article
|
|
|
258
268
|
<div
|
|
259
269
|
class="flourish flourish--iFrame"
|
|
260
270
|
data-component="flourish"
|
|
271
|
+
data-component-id="123"
|
|
272
|
+
data-component-type="flourish-topper"
|
|
261
273
|
data-layout-width="full-grid"
|
|
262
274
|
>
|
|
263
275
|
<iframe
|
|
@@ -2,6 +2,7 @@ import React, { createElement } from 'react'
|
|
|
2
2
|
import { render } from '@testing-library/react'
|
|
3
3
|
import RichText from '.'
|
|
4
4
|
import { ContentTree } from '@financial-times/content-tree'
|
|
5
|
+
import { Body } from '@financial-times/cp-content-pipeline-schema/src/resolvers/content-tree/Workarounds'
|
|
5
6
|
|
|
6
7
|
describe('<RichText />', () => {
|
|
7
8
|
it('renders a content-tree using built-in components', () => {
|
|
@@ -31,18 +32,18 @@ describe('<RichText />', () => {
|
|
|
31
32
|
|
|
32
33
|
it('adds a key property to all child components', () => {
|
|
33
34
|
jest.spyOn(React, 'createElement')
|
|
34
|
-
const tree:
|
|
35
|
+
const tree: Body = {
|
|
35
36
|
type: 'body',
|
|
36
37
|
version: 1,
|
|
37
38
|
children: [
|
|
38
39
|
{
|
|
39
|
-
type: '
|
|
40
|
-
children: [{ type: 'text', value: 'first
|
|
41
|
-
}
|
|
40
|
+
type: 'paragraph',
|
|
41
|
+
children: [{ type: 'text', value: 'first paragraph' }],
|
|
42
|
+
},
|
|
42
43
|
{
|
|
43
|
-
type: '
|
|
44
|
-
children: [{ type: 'text', value: 'second
|
|
45
|
-
}
|
|
44
|
+
type: 'paragraph',
|
|
45
|
+
children: [{ type: 'text', value: 'second paragraph' }],
|
|
46
|
+
},
|
|
46
47
|
],
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -62,20 +63,20 @@ describe('<RichText />', () => {
|
|
|
62
63
|
})
|
|
63
64
|
|
|
64
65
|
it("ignores components that it doesn't have a mapping for", () => {
|
|
65
|
-
const tree:
|
|
66
|
+
const tree: Body = {
|
|
66
67
|
type: 'body',
|
|
67
68
|
version: 1,
|
|
68
69
|
children: [
|
|
69
70
|
{
|
|
70
|
-
type: '
|
|
71
|
+
type: 'paragraph',
|
|
71
72
|
children: [{ type: 'text', value: 'i should render' }],
|
|
72
|
-
}
|
|
73
|
+
},
|
|
73
74
|
{
|
|
74
75
|
type: 'unknown',
|
|
75
76
|
children: [
|
|
76
77
|
{ type: 'text', value: 'i should not render' } as ContentTree.Text,
|
|
77
78
|
],
|
|
78
|
-
} as ContentTree.
|
|
79
|
+
} as unknown as ContentTree.Paragraph,
|
|
79
80
|
],
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -87,13 +88,13 @@ describe('<RichText />', () => {
|
|
|
87
88
|
<RichText structuredContent={structuredContent} />
|
|
88
89
|
)
|
|
89
90
|
|
|
90
|
-
expect(getByText('i should render').tagName).toEqual('
|
|
91
|
+
expect(getByText('i should render').tagName).toEqual('P')
|
|
91
92
|
//wrapping component with react-testing-library is a div
|
|
92
93
|
expect(getByText('i should not render').tagName).toEqual('DIV')
|
|
93
94
|
})
|
|
94
95
|
|
|
95
96
|
it('adds references as props', () => {
|
|
96
|
-
const tree:
|
|
97
|
+
const tree: Body = {
|
|
97
98
|
type: 'body',
|
|
98
99
|
version: 1,
|
|
99
100
|
children: [
|