@financial-times/cp-content-pipeline-ui 7.3.0 → 7.4.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 CHANGED
@@ -574,6 +574,14 @@
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
+ ## [7.3.1](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v7.3.0...cp-content-pipeline-ui-v7.3.1) (2024-10-09)
578
+
579
+
580
+ ### Bug Fixes
581
+
582
+ * remove duplicate id in ccc elements ([deadf51](https://github.com/Financial-Times/cp-content-pipeline/commit/deadf51f8a29da8da93c33bf129d25c354d1f565))
583
+ * return early if already initialised ([ab7860d](https://github.com/Financial-Times/cp-content-pipeline/commit/ab7860d2e9299122893384a1afc3104307e4fc71))
584
+
577
585
  ## [7.3.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-ui-v7.2.1...cp-content-pipeline-ui-v7.3.0) (2024-10-07)
578
586
 
579
587
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  export type MessageProps = {
3
- id: string;
3
+ id?: string;
4
4
  type?: string;
5
5
  state?: string;
6
6
  text?: string;
@@ -11,7 +11,7 @@ declare class CustomCodeComponentClient {
11
11
  */
12
12
  tracking: CustomCodeComponentTracker;
13
13
  constructor(el: Element);
14
- static init(rootEl?: Element): (CustomCodeComponentClient | undefined)[];
14
+ static init(rootEl?: Element): CustomCodeComponentClient[] | void;
15
15
  static destroy(components: CustomCodeComponentClient[]): void;
16
16
  }
17
17
  export default CustomCodeComponentClient;
@@ -20,7 +20,12 @@ class CustomCodeComponentClient {
20
20
  }
21
21
  static init(rootEl) {
22
22
  const root = rootEl instanceof Element ? rootEl : document;
23
- return Array.from(root.querySelectorAll('custom-code-component')).map((el) => new CustomCodeComponentClient(el));
23
+ return Array.from(root.querySelectorAll('custom-code-component')).reduce((acc, el) => {
24
+ if (!el.hasAttribute('data-o-tracking-initialised')) {
25
+ acc.push(new CustomCodeComponentClient(el));
26
+ }
27
+ return acc;
28
+ }, []);
24
29
  }
25
30
  static destroy(components) {
26
31
  components.forEach((component) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/content-tree/CustomCodeComponent/client/index.ts"],"names":[],"mappings":";;AAAA,yCAAuD;AAEvD;;;;;GAKG;AACH,MAAM,yBAAyB;IAM7B,YAAY,EAAW;QACrB,MAAM,YAAY,GAAG;YACnB,SAAS,EAAE;gBACT,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC/B,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE;gBACnC,IAAI,EAAE,uBAAuB;aAC9B;SACF,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,qCAA0B,CAAC,EAAa,EAAE,YAAY,CAAC,CAAA;IAC7E,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,MAAgB;QAC1B,MAAM,IAAI,GAAG,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC,GAAG,CACnE,CAAC,EAAW,EAAE,EAAE,CAAC,IAAI,yBAAyB,CAAC,EAAE,CAAC,CACnD,CAAA;IACH,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,UAAuC;QACpD,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;QAC9B,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAED,kBAAe,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/components/content-tree/CustomCodeComponent/client/index.ts"],"names":[],"mappings":";;AAAA,yCAAuD;AAEvD;;;;;GAKG;AACH,MAAM,yBAAyB;IAM7B,YAAY,EAAW;QACrB,MAAM,YAAY,GAAG;YACnB,SAAS,EAAE;gBACT,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC/B,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE;gBACnC,IAAI,EAAE,uBAAuB;aAC9B;SACF,CAAA;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,qCAA0B,CAC5C,EAAiB,EACjB,YAAY,CACb,CAAA;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,MAAgB;QAC1B,MAAM,IAAI,GAAG,MAAM,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAEtE,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE;YACZ,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,6BAA6B,CAAC,EAAE,CAAC;gBACpD,GAAG,CAAC,IAAI,CAAC,IAAI,yBAAyB,CAAC,EAAE,CAAC,CAAC,CAAA;YAC7C,CAAC;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,EAAE,EAAE,CAAC,CAAA;IACR,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,UAAuC;QACpD,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAC/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;QAC9B,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAED,kBAAe,yBAAyB,CAAA"}
@@ -16,10 +16,12 @@ type TrackingData = {
16
16
  declare class CustomCodeComponentTracker {
17
17
  private component;
18
18
  private trackingData;
19
- private observer;
20
- private viewing;
21
- constructor(component: Element, trackingData: TrackingData);
19
+ private mutationObserver?;
20
+ private intersectionObserver?;
21
+ private viewing?;
22
+ constructor(component: HTMLElement, trackingData: TrackingData);
22
23
  private init;
24
+ private mutationCallback;
23
25
  private onCccConnected;
24
26
  private onCccError;
25
27
  private onView;
@@ -13,31 +13,52 @@ class CustomCodeComponentTracker {
13
13
  this.trackingData = trackingData;
14
14
  this.component = component;
15
15
  this.trackingData = trackingData;
16
- // this needs to instantiated here so that it can be accessed correctly in the destroy method
16
+ // we're using a mutation observer to watch for changes to the component rather than event listeners
17
+ // as dynamic imports in the app are run before the tracking client can be instantiated on second
18
+ // and subsequent page visits in a session
19
+ // the observers need to instantiated here so that they can be accessed correctly in the destroy method
17
20
  // called by the app
18
- this.observer = new IntersectionObserver(this.onChange.bind(this), {
21
+ this.mutationObserver = new MutationObserver(this.mutationCallback.bind(this));
22
+ this.mutationObserver.observe(this.component, {
23
+ attributes: true,
24
+ attributeFilter: ['data-ccc-ready', 'data-ccc-error'],
25
+ });
26
+ this.intersectionObserver = new IntersectionObserver(this.onChange.bind(this), {
19
27
  rootMargin: `0px 0px -300px 0px`,
20
28
  threshold: 0,
21
29
  });
22
- this.observer.observe(this.component);
30
+ this.intersectionObserver.observe(this.component);
23
31
  this.viewing = false;
24
32
  this.destroy = this.destroy.bind(this);
25
33
  this.init();
26
34
  }
27
35
  init() {
28
- if (this.component.hasAttribute('data-o-tracking-initialised')) {
29
- return;
30
- }
31
36
  this.dispatchEvent('mount');
32
- this.component.addEventListener('error', this.onCccError.bind(this));
33
- this.component.addEventListener('ccc-connected', this.onCccConnected.bind(this));
37
+ if (this.component.dataset.cccError) {
38
+ this.onCccError();
39
+ }
40
+ if (this.component.dataset.cccReady) {
41
+ this.onCccConnected();
42
+ }
34
43
  this.component.setAttribute('data-o-tracking-initialised', 'true');
35
44
  }
45
+ mutationCallback(mutationsList) {
46
+ for (const mutation of mutationsList) {
47
+ if (mutation.attributeName === 'data-ccc-ready') {
48
+ this.onCccConnected();
49
+ }
50
+ if (mutation.attributeName === 'data-ccc-error') {
51
+ this.onCccError();
52
+ }
53
+ }
54
+ }
36
55
  onCccConnected() {
37
56
  this.dispatchEvent('act', { trigger_action: 'success' });
38
57
  }
39
58
  onCccError() {
40
- this.dispatchEvent('act', { trigger_action: 'error' });
59
+ this.dispatchEvent('act', {
60
+ trigger_action: `error: ${this.component.dataset.cccError}`,
61
+ });
41
62
  }
42
63
  onView() {
43
64
  this.dispatchEvent('view');
@@ -75,15 +96,13 @@ class CustomCodeComponentTracker {
75
96
  });
76
97
  }
77
98
  destroy() {
78
- if (this.observer && this.component) {
79
- this.observer.unobserve(this.component);
80
- this.observer.disconnect();
81
- this.component.removeEventListener('ccc-connected', this.onCccConnected.bind(this));
82
- this.component.removeEventListener('error', this.onCccError.bind(this));
83
- if (this.viewing) {
84
- this.onExitView();
85
- }
86
- }
99
+ if (!this.component)
100
+ return;
101
+ this.component.removeAttribute('data-o-tracking-initialised');
102
+ this.mutationObserver?.disconnect();
103
+ this.intersectionObserver?.unobserve(this.component);
104
+ this.intersectionObserver?.disconnect();
105
+ this.viewing && this.onExitView();
87
106
  }
88
107
  }
89
108
  exports.CustomCodeComponentTracker = CustomCodeComponentTracker;
@@ -1 +1 @@
1
- {"version":3,"file":"tracking.js","sourceRoot":"","sources":["../../../../../src/components/content-tree/CustomCodeComponent/client/tracking.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tracking.js","sourceRoot":"","sources":["../../../../../src/components/content-tree/CustomCodeComponent/client/tracking.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ const RichText_1 = __importDefault(require("../../RichText"));
10
10
  const CustomCodeComponent = ({ content: { path, versionRange, id, layoutWidth = 'in-line', attributes = {}, body, }, }) => {
11
11
  return (react_1.default.createElement(Layout_1.Layout, { content: { type: 'layout', layoutName: 'auto', layoutWidth: layoutWidth } },
12
12
  react_1.default.createElement("custom-code-component", { path: path, version: versionRange, ...attributes, id: id },
13
- react_1.default.createElement(Message_1.default, { id: id, type: "notice", state: "inform" }),
13
+ react_1.default.createElement(Message_1.default, { type: "notice", state: "inform" }),
14
14
  body?.structured && react_1.default.createElement(RichText_1.default, { structuredContent: body.structured }))));
15
15
  };
16
16
  exports.default = CustomCodeComponent;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/content-tree/CustomCodeComponent/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4DAAmC;AACnC,sCAAkC;AAClC,8DAAqC;AAqBrC,MAAM,mBAAmB,GAErB,CAAC,EACH,OAAO,EAAE,EACP,IAAI,EACJ,YAAY,EACZ,EAAE,EACF,WAAW,GAAG,SAAS,EACvB,UAAU,GAAG,EAAE,EACf,IAAI,GACL,GACwB,EAAE,EAAE;IAC7B,OAAO,CACL,8BAAC,eAAM,IACL,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE;QAEzE,yDACE,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,YAAY,KACjB,UAAU,EACd,EAAE,EAAE,EAAE;YAEN,8BAAC,iBAAO,IAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAC,QAAQ,GAAG;YAC/C,IAAI,EAAE,UAAU,IAAI,8BAAC,kBAAQ,IAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,GAAI,CAC/C,CACjB,CACV,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/content-tree/CustomCodeComponent/index.tsx"],"names":[],"mappings":";;;;;AAAA,kDAAyB;AACzB,4DAAmC;AACnC,sCAAkC;AAClC,8DAAqC;AAqBrC,MAAM,mBAAmB,GAErB,CAAC,EACH,OAAO,EAAE,EACP,IAAI,EACJ,YAAY,EACZ,EAAE,EACF,WAAW,GAAG,SAAS,EACvB,UAAU,GAAG,EAAE,EACf,IAAI,GACL,GACwB,EAAE,EAAE;IAC7B,OAAO,CACL,8BAAC,eAAM,IACL,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE;QAEzE,yDACE,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,YAAY,KACjB,UAAU,EACd,EAAE,EAAE,EAAE;YAEN,8BAAC,iBAAO,IAAC,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAC,QAAQ,GAAG;YACvC,IAAI,EAAE,UAAU,IAAI,8BAAC,kBAAQ,IAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,GAAI,CAC/C,CACjB,CACV,CAAA;AACH,CAAC,CAAA;AAED,kBAAe,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cp-content-pipeline-ui",
3
- "version": "7.3.0",
3
+ "version": "7.4.0-beta.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -2,7 +2,7 @@ import React from 'react'
2
2
  import classnames from 'classnames'
3
3
 
4
4
  export type MessageProps = {
5
- id: string
5
+ id?: string
6
6
  type?: string
7
7
  state?: string
8
8
  text?: string
@@ -20,14 +20,22 @@ class CustomCodeComponentClient {
20
20
  type: 'custom-code-component',
21
21
  },
22
22
  }
23
- this.tracking = new CustomCodeComponentTracker(el as Element, trackingData)
23
+ this.tracking = new CustomCodeComponentTracker(
24
+ el as HTMLElement,
25
+ trackingData
26
+ )
24
27
  }
25
28
 
26
- static init(rootEl?: Element): (CustomCodeComponentClient | undefined)[] {
29
+ static init(rootEl?: Element): CustomCodeComponentClient[] | void {
27
30
  const root = rootEl instanceof Element ? rootEl : document
28
- return Array.from(root.querySelectorAll('custom-code-component')).map(
29
- (el: Element) => new CustomCodeComponentClient(el)
30
- )
31
+ return Array.from(root.querySelectorAll('custom-code-component')).reduce<
32
+ CustomCodeComponentClient[]
33
+ >((acc, el) => {
34
+ if (!el.hasAttribute('data-o-tracking-initialised')) {
35
+ acc.push(new CustomCodeComponentClient(el))
36
+ }
37
+ return acc
38
+ }, [])
31
39
  }
32
40
 
33
41
  static destroy(components: CustomCodeComponentClient[]): void {
@@ -16,43 +16,73 @@ type TrackingData = {
16
16
  * @param {TrackingData} trackingData - The specific component data
17
17
  */
18
18
  class CustomCodeComponentTracker {
19
- private observer: IntersectionObserver
20
- private viewing: boolean
19
+ private mutationObserver?: MutationObserver
20
+ private intersectionObserver?: IntersectionObserver
21
+ private viewing?: boolean
21
22
 
22
- constructor(private component: Element, private trackingData: TrackingData) {
23
+ constructor(
24
+ private component: HTMLElement,
25
+ private trackingData: TrackingData
26
+ ) {
23
27
  this.component = component
24
28
  this.trackingData = trackingData
25
- // this needs to instantiated here so that it can be accessed correctly in the destroy method
29
+ // we're using a mutation observer to watch for changes to the component rather than event listeners
30
+ // as dynamic imports in the app are run before the tracking client can be instantiated on second
31
+ // and subsequent page visits in a session
32
+ // the observers need to instantiated here so that they can be accessed correctly in the destroy method
26
33
  // called by the app
27
- this.observer = new IntersectionObserver(this.onChange.bind(this), {
28
- rootMargin: `0px 0px -300px 0px`,
29
- threshold: 0,
34
+ this.mutationObserver = new MutationObserver(
35
+ this.mutationCallback.bind(this)
36
+ )
37
+ this.mutationObserver.observe(this.component, {
38
+ attributes: true,
39
+ attributeFilter: ['data-ccc-ready', 'data-ccc-error'],
30
40
  })
31
- this.observer.observe(this.component)
41
+ this.intersectionObserver = new IntersectionObserver(
42
+ this.onChange.bind(this),
43
+ {
44
+ rootMargin: `0px 0px -300px 0px`,
45
+ threshold: 0,
46
+ }
47
+ )
48
+ this.intersectionObserver.observe(this.component)
32
49
  this.viewing = false
33
50
  this.destroy = this.destroy.bind(this)
34
51
  this.init()
35
52
  }
36
53
 
37
54
  private init() {
38
- if (this.component.hasAttribute('data-o-tracking-initialised')) {
39
- return
40
- }
41
55
  this.dispatchEvent('mount')
42
- this.component.addEventListener('error', this.onCccError.bind(this))
43
- this.component.addEventListener(
44
- 'ccc-connected',
45
- this.onCccConnected.bind(this)
46
- )
56
+ if (this.component.dataset.cccError) {
57
+ this.onCccError()
58
+ }
59
+
60
+ if (this.component.dataset.cccReady) {
61
+ this.onCccConnected()
62
+ }
63
+
47
64
  this.component.setAttribute('data-o-tracking-initialised', 'true')
48
65
  }
49
66
 
67
+ private mutationCallback(mutationsList: MutationRecord[]): void {
68
+ for (const mutation of mutationsList) {
69
+ if (mutation.attributeName === 'data-ccc-ready') {
70
+ this.onCccConnected()
71
+ }
72
+ if (mutation.attributeName === 'data-ccc-error') {
73
+ this.onCccError()
74
+ }
75
+ }
76
+ }
77
+
50
78
  private onCccConnected(): void {
51
79
  this.dispatchEvent('act', { trigger_action: 'success' })
52
80
  }
53
81
 
54
82
  private onCccError(): void {
55
- this.dispatchEvent('act', { trigger_action: 'error' })
83
+ this.dispatchEvent('act', {
84
+ trigger_action: `error: ${this.component.dataset.cccError}`,
85
+ })
56
86
  }
57
87
 
58
88
  private onView(): void {
@@ -99,18 +129,14 @@ class CustomCodeComponentTracker {
99
129
  }
100
130
 
101
131
  destroy(): void {
102
- if (this.observer && this.component) {
103
- this.observer.unobserve(this.component)
104
- this.observer.disconnect()
105
- this.component.removeEventListener(
106
- 'ccc-connected',
107
- this.onCccConnected.bind(this)
108
- )
109
- this.component.removeEventListener('error', this.onCccError.bind(this))
110
- if (this.viewing) {
111
- this.onExitView()
112
- }
113
- }
132
+ if (!this.component) return
133
+
134
+ this.component.removeAttribute('data-o-tracking-initialised')
135
+ this.mutationObserver?.disconnect()
136
+ this.intersectionObserver?.unobserve(this.component)
137
+ this.intersectionObserver?.disconnect()
138
+
139
+ this.viewing && this.onExitView()
114
140
  }
115
141
  }
116
142
 
@@ -44,7 +44,7 @@ const CustomCodeComponent: React.FC<
44
44
  {...attributes}
45
45
  id={id}
46
46
  >
47
- <Message id={id} type="notice" state="inform" />
47
+ <Message type="notice" state="inform" />
48
48
  {body?.structured && <RichText structuredContent={body.structured} />}
49
49
  </custom-code-component>
50
50
  </Layout>