@financial-times/custom-code-component 2.1.4 → 2.1.6
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/custom-element.d.ts +1 -0
- package/dist/custom-element.js +58 -51
- package/dist/custom-element.js.map +1 -1
- package/package.json +1 -1
- package/src/custom-code-component.ts +4 -4
- package/src/logger.ts +20 -4
package/dist/custom-element.d.ts
CHANGED
package/dist/custom-element.js
CHANGED
|
@@ -117,12 +117,12 @@ const u = Object.freeze({
|
|
|
117
117
|
ERROR: 3,
|
|
118
118
|
TEST: 4,
|
|
119
119
|
DEFAULT: 2
|
|
120
|
-
}),
|
|
120
|
+
}), L = "CCC:";
|
|
121
121
|
function S(o) {
|
|
122
122
|
const t = o == null ? void 0 : o.toLowerCase();
|
|
123
123
|
return t === "debug" ? u.DEBUG : t === "info" ? u.INFO : t === "warn" ? u.WARN : t === "error" ? u.ERROR : t === "test" ? u.TEST : u.DEFAULT;
|
|
124
124
|
}
|
|
125
|
-
class
|
|
125
|
+
class x {
|
|
126
126
|
constructor({
|
|
127
127
|
level: t = u.DEFAULT,
|
|
128
128
|
component: e
|
|
@@ -131,17 +131,24 @@ class P {
|
|
|
131
131
|
}) {
|
|
132
132
|
this.log = this.debug, this.level = localStorage != null && localStorage.getItem("CCC_LOG_LEVEL") ? S(localStorage.getItem("CCC_LOG_LEVEL")) : t, this.component = e;
|
|
133
133
|
}
|
|
134
|
+
formatConsoleArgs(t) {
|
|
135
|
+
const e = this.component ? [this.component] : [];
|
|
136
|
+
if (t.length === 0)
|
|
137
|
+
return [L, ...e];
|
|
138
|
+
const [n, ...r] = t;
|
|
139
|
+
return typeof n == "string" ? [`${L} ${n}`, ...r, ...e] : [L, n, ...r, ...e];
|
|
140
|
+
}
|
|
134
141
|
debug(...t) {
|
|
135
|
-
this.level <= u.DEBUG && console.info(
|
|
142
|
+
this.level <= u.DEBUG && console.info(...this.formatConsoleArgs(t));
|
|
136
143
|
}
|
|
137
144
|
info(...t) {
|
|
138
|
-
this.level <= u.INFO && console.info(
|
|
145
|
+
this.level <= u.INFO && console.info(...this.formatConsoleArgs(t));
|
|
139
146
|
}
|
|
140
147
|
warn(...t) {
|
|
141
|
-
this.level <= u.WARN && console.warn(
|
|
148
|
+
this.level <= u.WARN && console.warn(...this.formatConsoleArgs(t));
|
|
142
149
|
}
|
|
143
150
|
error(...t) {
|
|
144
|
-
this.level <= u.ERROR && console.error(
|
|
151
|
+
this.level <= u.ERROR && console.error(...this.formatConsoleArgs(t));
|
|
145
152
|
}
|
|
146
153
|
setLogLevel(t) {
|
|
147
154
|
localStorage != null && localStorage.getItem("CCC_LOG_LEVEL") ? this.level = S(localStorage.getItem("CCC_LOG_LEVEL")) : typeof t == "number" ? this.level = t : this.level = S(t);
|
|
@@ -154,7 +161,7 @@ const M = (o, t, e) => {
|
|
|
154
161
|
siblings: n.length,
|
|
155
162
|
position: r
|
|
156
163
|
};
|
|
157
|
-
},
|
|
164
|
+
}, P = [
|
|
158
165
|
"nodeName",
|
|
159
166
|
"className",
|
|
160
167
|
"id",
|
|
@@ -163,7 +170,7 @@ const M = (o, t, e) => {
|
|
|
163
170
|
"role"
|
|
164
171
|
], F = (o) => {
|
|
165
172
|
const t = {};
|
|
166
|
-
for (const e of
|
|
173
|
+
for (const e of P) {
|
|
167
174
|
const n = o[e] || o.getAttribute(e) || o.hasAttribute(e);
|
|
168
175
|
n !== void 0 && (typeof n == "boolean" ? t[e] = n : t[e] = N(n));
|
|
169
176
|
}
|
|
@@ -184,7 +191,7 @@ const M = (o, t, e) => {
|
|
|
184
191
|
t[e.name] = e.value;
|
|
185
192
|
}), t), Y = (o, t, e) => {
|
|
186
193
|
const n = {};
|
|
187
|
-
return e &&
|
|
194
|
+
return e && P.forEach((r) => {
|
|
188
195
|
typeof t[r] < "u" && r !== "id" && (n[r] = t[r]);
|
|
189
196
|
}), o.filter((r) => r.name.match(/^data-trackable-context-/i)).forEach((r) => {
|
|
190
197
|
n[r.name.replace("data-trackable-context-", "")] = j(r.value);
|
|
@@ -216,7 +223,7 @@ class G {
|
|
|
216
223
|
elements: c = 'a, button, input, [role="button"]',
|
|
217
224
|
logger: a
|
|
218
225
|
}) {
|
|
219
|
-
this.cccId = t, this.cccName = e, this.subtype = n, this.teamName = r, this.shadowRoot = s, this.category = i, this.elements = c, this.isInitialised = !1, this.log = a ?? new
|
|
226
|
+
this.cccId = t, this.cccName = e, this.subtype = n, this.teamName = r, this.shadowRoot = s, this.category = i, this.elements = c, this.isInitialised = !1, this.log = a ?? new x();
|
|
220
227
|
}
|
|
221
228
|
// Get properties for the event (as opposed to properties of the clicked element)
|
|
222
229
|
getEventProperties(t) {
|
|
@@ -292,14 +299,14 @@ class G {
|
|
|
292
299
|
(t = this.shadowDelegate) == null || t.off();
|
|
293
300
|
}
|
|
294
301
|
}
|
|
295
|
-
class
|
|
302
|
+
class f {
|
|
296
303
|
constructor(t) {
|
|
297
304
|
this.org = "local", this.repo = "dev";
|
|
298
|
-
const { org: e, repo: n, name: r, versionRange: s } = T(t) ? t :
|
|
305
|
+
const { org: e, repo: n, name: r, versionRange: s } = T(t) ? t : f.fromString(t);
|
|
299
306
|
e && (this.org = e), n && (this.repo = n), this.name = r, this.versionRange = s;
|
|
300
307
|
}
|
|
301
308
|
set path(t) {
|
|
302
|
-
const { org: e, repo: n, name: r, versionRange: s } = T(t) ? t :
|
|
309
|
+
const { org: e, repo: n, name: r, versionRange: s } = T(t) ? t : f.fromString(t);
|
|
303
310
|
this.org = e, this.repo = n, this.name = r, this.versionRange = s;
|
|
304
311
|
}
|
|
305
312
|
get path() {
|
|
@@ -316,42 +323,42 @@ class d {
|
|
|
316
323
|
static fromString(t, e) {
|
|
317
324
|
var a;
|
|
318
325
|
const n = t ?? "unknown/unknown/unknown", [r, s, i] = n.replace(/@[^\/]+/, "").split("/").reverse(), c = e ?? ((a = n.match(/@[^\/]+/)) == null ? void 0 : a.toString().replace("@", "")) ?? "unknown";
|
|
319
|
-
if (s && !c) throw new
|
|
320
|
-
return new
|
|
326
|
+
if (s && !c) throw new d("No version specified");
|
|
327
|
+
return new f({ org: i, repo: s, name: r, versionRange: c });
|
|
321
328
|
}
|
|
322
329
|
}
|
|
323
330
|
function T(o) {
|
|
324
331
|
return typeof o == "object" && o !== null ? "org" in o && "repo" in o && "name" in o : !1;
|
|
325
332
|
}
|
|
326
|
-
class
|
|
333
|
+
class d extends Error {
|
|
327
334
|
constructor(t, e) {
|
|
328
335
|
var n;
|
|
329
336
|
!e && t ? (super(t), this.component = null) : typeof (e == null ? void 0 : e.component) == "string" ? (super(
|
|
330
337
|
t ?? `${e.cause ?? "Unknown error"} in ${e.component} imported from ${e.source ?? "an undefined source"}.`
|
|
331
|
-
), this.component =
|
|
338
|
+
), this.component = f.fromString(e.component)) : T(e == null ? void 0 : e.component) ? (super(
|
|
332
339
|
t ?? `${e.cause ?? "Unknown error"} in ${e.component.org}/${e.component.repo}/${e.component.name}@${e.component.versionRange} imported from ${e.source ?? "an undefined source"}.`
|
|
333
|
-
), this.component = new
|
|
340
|
+
), this.component = new f(e.component)) : (super(
|
|
334
341
|
`${(e == null ? void 0 : e.cause) ?? "Unknown error"} in unknown component imported from ${(e == null ? void 0 : e.source) ?? "unknown source"}.`
|
|
335
|
-
), this.component = null), this.source = (e == null ? void 0 : e.source) ?? "unknown source", this.errors = [], e != null && e.error && ((n = this.errors) == null || n.push(e == null ? void 0 : e.error)), Error.captureStackTrace && Error.captureStackTrace(this,
|
|
342
|
+
), this.component = null), this.source = (e == null ? void 0 : e.source) ?? "unknown source", this.errors = [], e != null && e.error && ((n = this.errors) == null || n.push(e == null ? void 0 : e.error)), Error.captureStackTrace && Error.captureStackTrace(this, d), this.name = "CCCError";
|
|
336
343
|
}
|
|
337
344
|
}
|
|
338
|
-
class
|
|
345
|
+
class w extends d {
|
|
339
346
|
constructor(t, e) {
|
|
340
347
|
super(t, { ...e, cause: "Import error" }), this.name = "CCCImportError";
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
|
-
class O extends
|
|
350
|
+
class O extends d {
|
|
344
351
|
constructor(t, e) {
|
|
345
352
|
super(t, { ...e, cause: "Render error" }), this.name = "CCCRenderError";
|
|
346
353
|
}
|
|
347
354
|
}
|
|
348
|
-
class J extends
|
|
355
|
+
class J extends d {
|
|
349
356
|
constructor(t) {
|
|
350
357
|
super(null, { ...t, cause: "Timeout error" }), this.name = "CCCTimeoutError";
|
|
351
358
|
}
|
|
352
359
|
}
|
|
353
|
-
const
|
|
354
|
-
constructor(t =
|
|
360
|
+
const E = class E extends Event {
|
|
361
|
+
constructor(t = E.eventType, e, n) {
|
|
355
362
|
super(t, {
|
|
356
363
|
bubbles: !0,
|
|
357
364
|
cancelable: !1,
|
|
@@ -360,29 +367,29 @@ const y = class y extends Event {
|
|
|
360
367
|
}), this.component = e.component, this.source = e.source;
|
|
361
368
|
}
|
|
362
369
|
};
|
|
363
|
-
|
|
364
|
-
let b =
|
|
365
|
-
const
|
|
370
|
+
E.eventType = "ccc:event";
|
|
371
|
+
let b = E;
|
|
372
|
+
const y = class y extends b {
|
|
366
373
|
constructor(t, e) {
|
|
367
|
-
super(
|
|
374
|
+
super(y.eventType, t, e);
|
|
368
375
|
}
|
|
369
376
|
};
|
|
370
|
-
|
|
371
|
-
let k =
|
|
372
|
-
const
|
|
377
|
+
y.eventType = "ccc:connected";
|
|
378
|
+
let k = y;
|
|
379
|
+
const v = class v extends b {
|
|
373
380
|
constructor(t, e) {
|
|
374
|
-
super(
|
|
381
|
+
super(v.eventType, t, e);
|
|
375
382
|
}
|
|
376
383
|
};
|
|
377
|
-
|
|
378
|
-
let A =
|
|
379
|
-
const
|
|
384
|
+
v.eventType = "ccc:ready";
|
|
385
|
+
let A = v;
|
|
386
|
+
const C = class C extends b {
|
|
380
387
|
constructor(t, e) {
|
|
381
|
-
super(
|
|
388
|
+
super(C.eventType, t, e), this.intersecting = !1, this.intersecting = t.intersecting, this.entry = t.entry;
|
|
382
389
|
}
|
|
383
390
|
};
|
|
384
|
-
|
|
385
|
-
let R =
|
|
391
|
+
C.eventType = "ccc:viewport";
|
|
392
|
+
let R = C;
|
|
386
393
|
const W = (o) => o.replace(
|
|
387
394
|
/[A-Z]+(?![a-z])|[A-Z]/g,
|
|
388
395
|
(t, e) => (e ? "-" : "") + t.toLowerCase()
|
|
@@ -453,7 +460,7 @@ class et extends HTMLElement {
|
|
|
453
460
|
"shadow-open",
|
|
454
461
|
"env",
|
|
455
462
|
"load-timeout"
|
|
456
|
-
]), this.component = new
|
|
463
|
+
]), this.component = new f(), this.ac = null, this.observer = new IntersectionObserver((e) => {
|
|
457
464
|
this.logger.debug("Intersection Observer callback", { entries: e }), e.forEach((n) => {
|
|
458
465
|
this.dispatchEvent(
|
|
459
466
|
new R({
|
|
@@ -499,7 +506,7 @@ class et extends HTMLElement {
|
|
|
499
506
|
`.trim(), document.head.appendChild(e);
|
|
500
507
|
const n = document.createElement("script");
|
|
501
508
|
n.type = "module", n.src = `${(s = this.testUrl) == null ? void 0 : s.origin}/@vite/client`, document.head.appendChild(n);
|
|
502
|
-
}, this.logger = new
|
|
509
|
+
}, this.logger = new x();
|
|
503
510
|
const t = HTMLElement.prototype.hasOwnProperty("attachInternals");
|
|
504
511
|
try {
|
|
505
512
|
const e = t && this.attachInternals();
|
|
@@ -516,7 +523,7 @@ class et extends HTMLElement {
|
|
|
516
523
|
var t;
|
|
517
524
|
try {
|
|
518
525
|
const e = this.getAttribute("path"), n = this.getAttribute("version");
|
|
519
|
-
this.component =
|
|
526
|
+
this.component = f.fromString(e, n), this.logger.component = this.component, this.logger.setLogLevel(this.getAttribute("log")), this.logger.debug("connectedCallback"), (t = this.ac) == null || t.abort(), this.ac = new AbortController(), this.app = await this.load(this.ac.signal), this.mount(), this.initTracking();
|
|
520
527
|
} catch (e) {
|
|
521
528
|
e instanceof Error && requestAnimationFrame(() => {
|
|
522
529
|
this.emitError(e);
|
|
@@ -529,7 +536,7 @@ class et extends HTMLElement {
|
|
|
529
536
|
* @param error
|
|
530
537
|
*/
|
|
531
538
|
emitError(t) {
|
|
532
|
-
if (this.logger.debug("emitError", { error: t }), t instanceof
|
|
539
|
+
if (this.logger.debug("emitError", { error: t }), t instanceof d)
|
|
533
540
|
this.dispatchEvent(
|
|
534
541
|
new ErrorEvent("ccc:error", {
|
|
535
542
|
bubbles: !0,
|
|
@@ -540,7 +547,7 @@ class et extends HTMLElement {
|
|
|
540
547
|
})
|
|
541
548
|
);
|
|
542
549
|
else {
|
|
543
|
-
const e = new
|
|
550
|
+
const e = new d(t.message, {
|
|
544
551
|
component: this.component,
|
|
545
552
|
error: t
|
|
546
553
|
});
|
|
@@ -664,13 +671,13 @@ class et extends HTMLElement {
|
|
|
664
671
|
shadowRoot: this.shadowRoot,
|
|
665
672
|
logger: this.logger
|
|
666
673
|
}), !i && Object.keys(c).length > 0 && (this.logger.warn(
|
|
667
|
-
|
|
674
|
+
"passing component settings as webcomponent attributes is %cDEPRECATED%c and will be removed in v3.",
|
|
668
675
|
"font-weight: bold",
|
|
669
|
-
"
|
|
676
|
+
""
|
|
670
677
|
), this.logger.warn(
|
|
671
|
-
"Please use the %cdata-component-props",
|
|
678
|
+
"Please use the %cdata-component-props%c attribute instead.",
|
|
672
679
|
"text-decoration: underline;",
|
|
673
|
-
"
|
|
680
|
+
""
|
|
674
681
|
));
|
|
675
682
|
const { onmessage: a, ready: h = Promise.resolve() } = this.app(
|
|
676
683
|
s,
|
|
@@ -746,7 +753,7 @@ class et extends HTMLElement {
|
|
|
746
753
|
if (m)
|
|
747
754
|
clearTimeout(p), h(m);
|
|
748
755
|
else
|
|
749
|
-
throw new
|
|
756
|
+
throw new w(
|
|
750
757
|
"No component renderer default export found",
|
|
751
758
|
{
|
|
752
759
|
component: this.component,
|
|
@@ -754,15 +761,15 @@ class et extends HTMLElement {
|
|
|
754
761
|
}
|
|
755
762
|
);
|
|
756
763
|
}).catch((m) => {
|
|
757
|
-
clearTimeout(p), this.logger.error(m), m instanceof Error && !(m instanceof
|
|
758
|
-
new
|
|
764
|
+
clearTimeout(p), this.logger.error(m), m instanceof Error && !(m instanceof w) ? l(
|
|
765
|
+
new w(m.message, {
|
|
759
766
|
component: this.component,
|
|
760
767
|
source: this.source
|
|
761
768
|
})
|
|
762
769
|
) : l(m);
|
|
763
770
|
});
|
|
764
771
|
else
|
|
765
|
-
throw clearTimeout(p), new
|
|
772
|
+
throw clearTimeout(p), new w(`Unable to mount ${e}`, {
|
|
766
773
|
component: this.component,
|
|
767
774
|
source: this.source
|
|
768
775
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-element.js","sources":["../node_modules/ftdomdelegate/main.js","../../node_modules/@financial-times/o-tracking/src/javascript/utils.js","../src/logger.ts","../src/get-trace.ts","../src/tracking.ts","../src/path.ts","../src/errors.ts","../src/events.ts","../src/util.ts","../src/environment.ts","../src/custom-code-component.ts"],"sourcesContent":["/**\n * DOM event delegator\n *\n * The delegator will listen\n * for events that bubble up\n * to the root node.\n *\n * @constructor\n * @param {Node|string} [root] The root node or a selector string matching the root node\n */\nfunction Delegate(root) {\n\n\t/**\n\t * Maintain a map of listener\n\t * lists, keyed by event name.\n\t *\n\t * @type Object\n\t */\n\tthis.listenerMap = [{}, {}];\n\tif (root) {\n\t\tthis.root(root);\n\t}\n\n\t/** @type function() */\n\tthis.handle = Delegate.prototype.handle.bind(this);\n\n\t// Cache of event listeners removed during an event cycle\n\tthis._removedListeners = [];\n}\n\n/**\n * Start listening for events\n * on the provided DOM element\n *\n * @param {Node|string} [root] The root node or a selector string matching the root node\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.root = function (root) {\n\tconst listenerMap = this.listenerMap;\n\tlet eventType;\n\n\t// Remove master event listeners\n\tif (this.rootElement) {\n\t\tfor (eventType in listenerMap[1]) {\n\t\t\tif (listenerMap[1].hasOwnProperty(eventType)) {\n\t\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, true);\n\t\t\t}\n\t\t}\n\t\tfor (eventType in listenerMap[0]) {\n\t\t\tif (listenerMap[0].hasOwnProperty(eventType)) {\n\t\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, false);\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no root or root is not\n\t// a dom node, then remove internal\n\t// root reference and exit here\n\tif (!root || !root.addEventListener) {\n\t\tif (this.rootElement) {\n\t\t\tdelete this.rootElement;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * The root node at which\n\t * listeners are attached.\n\t *\n\t * @type Node\n\t */\n\tthis.rootElement = root;\n\n\t// Set up master event listeners\n\tfor (eventType in listenerMap[1]) {\n\t\tif (listenerMap[1].hasOwnProperty(eventType)) {\n\t\t\tthis.rootElement.addEventListener(eventType, this.handle, true);\n\t\t}\n\t}\n\tfor (eventType in listenerMap[0]) {\n\t\tif (listenerMap[0].hasOwnProperty(eventType)) {\n\t\t\tthis.rootElement.addEventListener(eventType, this.handle, false);\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * @param {string} eventType\n * @returns boolean\n */\nDelegate.prototype.captureForType = function (eventType) {\n\treturn ['blur', 'error', 'focus', 'load', 'resize', 'scroll'].indexOf(eventType) !== -1;\n};\n\n/**\n * Attach a handler to one\n * event for all elements\n * that match the selector,\n * now or in the future\n *\n * The handler function receives\n * three arguments: the DOM event\n * object, the node that matched\n * the selector while the event\n * was bubbling and a reference\n * to itself. Within the handler,\n * 'this' is equal to the second\n * argument.\n *\n * The node that actually received\n * the event can be accessed via\n * 'event.target'.\n *\n * @param {string} eventType Listen for these events\n * @param {string|undefined} selector Only handle events on elements matching this selector, if undefined match root element\n * @param {function()} handler Handler function - event data passed here will be in event.data\n * @param {boolean} [useCapture] see 'useCapture' in <https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener>\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.on = function (eventType, selector, handler, useCapture) {\n\tlet root;\n\tlet listenerMap;\n\tlet matcher;\n\tlet matcherParam;\n\n\tif (!eventType) {\n\t\tthrow new TypeError('Invalid event type: ' + eventType);\n\t}\n\n\t// handler can be passed as\n\t// the second or third argument\n\tif (typeof selector === 'function') {\n\t\tuseCapture = handler;\n\t\thandler = selector;\n\t\tselector = null;\n\t}\n\n\t// Fallback to sensible defaults\n\t// if useCapture not set\n\tif (useCapture === undefined) {\n\t\tuseCapture = this.captureForType(eventType);\n\t}\n\n\tif (typeof handler !== 'function') {\n\t\tthrow new TypeError('Handler must be a type of Function');\n\t}\n\n\troot = this.rootElement;\n\tlistenerMap = this.listenerMap[useCapture ? 1 : 0];\n\n\t// Add master handler for type if not created yet\n\tif (!listenerMap[eventType]) {\n\t\tif (root) {\n\t\t\troot.addEventListener(eventType, this.handle, useCapture);\n\t\t}\n\t\tlistenerMap[eventType] = [];\n\t}\n\n\tif (!selector) {\n\t\tmatcherParam = null;\n\n\t\t// COMPLEX - matchesRoot needs to have access to\n\t\t// this.rootElement, so bind the function to this.\n\t\tmatcher = matchesRoot.bind(this);\n\n\t\t// Compile a matcher for the given selector\n\t} else if (/^[a-z]+$/i.test(selector)) {\n\t\tmatcherParam = selector;\n\t\tmatcher = matchesTag;\n\t} else if (/^#[a-z0-9\\-_]+$/i.test(selector)) {\n\t\tmatcherParam = selector.slice(1);\n\t\tmatcher = matchesId;\n\t} else {\n\t\tmatcherParam = selector;\n\t\tmatcher = Element.prototype.matches;\n\t}\n\n\t// Add to the list of listeners\n\tlistenerMap[eventType].push({\n\t\tselector: selector,\n\t\thandler: handler,\n\t\tmatcher: matcher,\n\t\tmatcherParam: matcherParam\n\t});\n\n\treturn this;\n};\n\n/**\n * Remove an event handler\n * for elements that match\n * the selector, forever\n *\n * @param {string} [eventType] Remove handlers for events matching this type, considering the other parameters\n * @param {string} [selector] If this parameter is omitted, only handlers which match the other two will be removed\n * @param {function()} [handler] If this parameter is omitted, only handlers which match the previous two will be removed\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.off = function (eventType, selector, handler, useCapture) {\n\tlet i;\n\tlet listener;\n\tlet listenerMap;\n\tlet listenerList;\n\tlet singleEventType;\n\n\t// Handler can be passed as\n\t// the second or third argument\n\tif (typeof selector === 'function') {\n\t\tuseCapture = handler;\n\t\thandler = selector;\n\t\tselector = null;\n\t}\n\n\t// If useCapture not set, remove\n\t// all event listeners\n\tif (useCapture === undefined) {\n\t\tthis.off(eventType, selector, handler, true);\n\t\tthis.off(eventType, selector, handler, false);\n\t\treturn this;\n\t}\n\n\tlistenerMap = this.listenerMap[useCapture ? 1 : 0];\n\tif (!eventType) {\n\t\tfor (singleEventType in listenerMap) {\n\t\t\tif (listenerMap.hasOwnProperty(singleEventType)) {\n\t\t\t\tthis.off(singleEventType, selector, handler);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tlistenerList = listenerMap[eventType];\n\tif (!listenerList || !listenerList.length) {\n\t\treturn this;\n\t}\n\n\t// Remove only parameter matches\n\t// if specified\n\tfor (i = listenerList.length - 1; i >= 0; i--) {\n\t\tlistener = listenerList[i];\n\n\t\tif ((!selector || selector === listener.selector) && (!handler || handler === listener.handler)) {\n\t\t\tthis._removedListeners.push(listener);\n\t\t\tlistenerList.splice(i, 1);\n\t\t}\n\t}\n\n\t// All listeners removed\n\tif (!listenerList.length) {\n\t\tdelete listenerMap[eventType];\n\n\t\t// Remove the main handler\n\t\tif (this.rootElement) {\n\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, useCapture);\n\t\t}\n\t}\n\n\treturn this;\n};\n\n\n/**\n * Handle an arbitrary event.\n *\n * @param {Event} event\n */\nDelegate.prototype.handle = function (event) {\n\tlet i;\n\tlet l;\n\tconst type = event.type;\n\tlet root;\n\tlet phase;\n\tlet listener;\n\tlet returned;\n\tlet listenerList = [];\n\tlet target;\n\tconst eventIgnore = 'ftLabsDelegateIgnore';\n\n\tif (event[eventIgnore] === true) {\n\t\treturn;\n\t}\n\n\ttarget = event.target;\n\n\t// Hardcode value of Node.TEXT_NODE\n\t// as not defined in IE8\n\tif (target.nodeType === 3) {\n\t\ttarget = target.parentNode;\n\t}\n\n\t// Handle SVG <use> elements in IE\n\tif (target.correspondingUseElement) {\n\t\ttarget = target.correspondingUseElement;\n\t}\n\n\troot = this.rootElement;\n\n\tphase = event.eventPhase || (event.target !== event.currentTarget ? 3 : 2);\n\n\t// eslint-disable-next-line default-case\n\tswitch (phase) {\n\t\tcase 1: //Event.CAPTURING_PHASE:\n\t\t\tlistenerList = this.listenerMap[1][type];\n\t\t\tbreak;\n\t\tcase 2: //Event.AT_TARGET:\n\t\t\tif (this.listenerMap[0] && this.listenerMap[0][type]) {\n\t\t\t\tlistenerList = listenerList.concat(this.listenerMap[0][type]);\n\t\t\t}\n\t\t\tif (this.listenerMap[1] && this.listenerMap[1][type]) {\n\t\t\t\tlistenerList = listenerList.concat(this.listenerMap[1][type]);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3: //Event.BUBBLING_PHASE:\n\t\t\tlistenerList = this.listenerMap[0][type];\n\t\t\tbreak;\n\t}\n\n\tlet toFire = [];\n\n\t// Need to continuously check\n\t// that the specific list is\n\t// still populated in case one\n\t// of the callbacks actually\n\t// causes the list to be destroyed.\n\tl = listenerList.length;\n\twhile (target && l) {\n\t\tfor (i = 0; i < l; i++) {\n\t\t\tlistener = listenerList[i];\n\n\t\t\t// Bail from this loop if\n\t\t\t// the length changed and\n\t\t\t// no more listeners are\n\t\t\t// defined between i and l.\n\t\t\tif (!listener) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ttarget.tagName &&\n\t\t\t\t[\"button\", \"input\", \"select\", \"textarea\"].indexOf(target.tagName.toLowerCase()) > -1 &&\n\t\t\t\ttarget.hasAttribute(\"disabled\")\n\t\t\t) {\n\t\t\t\t// Remove things that have previously fired\n\t\t\t\ttoFire = [];\n\t\t\t}\n\t\t\t// Check for match and fire\n\t\t\t// the event if there's one\n\t\t\t//\n\t\t\t// TODO:MCG:20120117: Need a way\n\t\t\t// to check if event#stopImmediatePropagation\n\t\t\t// was called. If so, break both loops.\n\t\t\telse if (listener.matcher.call(target, listener.matcherParam, target)) {\n\t\t\t\ttoFire.push([event, target, listener]);\n\t\t\t}\n\t\t}\n\n\t\t// TODO:MCG:20120117: Need a way to\n\t\t// check if event#stopPropagation\n\t\t// was called. If so, break looping\n\t\t// through the DOM. Stop if the\n\t\t// delegation root has been reached\n\t\tif (target === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tl = listenerList.length;\n\n\t\t// Fall back to parentNode since SVG children have no parentElement in IE\n\t\ttarget = target.parentElement || target.parentNode;\n\n\t\t// Do not traverse up to document root when using parentNode, though\n\t\tif (target instanceof HTMLDocument) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet ret;\n\n\tfor (i = 0; i < toFire.length; i++) {\n\t\t// Has it been removed during while the event function was fired\n\t\tif (this._removedListeners.indexOf(toFire[i][2]) > -1) {\n\t\t\tcontinue;\n\t\t}\n\t\treturned = this.fire.apply(this, toFire[i]);\n\n\t\t// Stop propagation to subsequent\n\t\t// callbacks if the callback returned\n\t\t// false\n\t\tif (returned === false) {\n\t\t\ttoFire[i][0][eventIgnore] = true;\n\t\t\ttoFire[i][0].preventDefault();\n\t\t\tret = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n/**\n * Fire a listener on a target.\n *\n * @param {Event} event\n * @param {Node} target\n * @param {Object} listener\n * @returns {boolean}\n */\nDelegate.prototype.fire = function (event, target, listener) {\n\treturn listener.handler.call(target, event, target);\n};\n\n/**\n * Check whether an element\n * matches a tag selector.\n *\n * Tags are NOT case-sensitive,\n * except in XML (and XML-based\n * languages such as XHTML).\n *\n * @param {string} tagName The tag name to test against\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesTag(tagName, element) {\n\treturn tagName.toLowerCase() === element.tagName.toLowerCase();\n}\n\n/**\n * Check whether an element\n * matches the root.\n *\n * @param {?String} selector In this case this is always passed through as null and not used\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesRoot(selector, element) {\n\tif (this.rootElement === window) {\n\t\treturn (\n\t\t\t// Match the outer document (dispatched from document)\n\t\t\telement === document ||\n\t\t\t// The <html> element (dispatched from document.body or document.documentElement)\n\t\t\telement === document.documentElement ||\n\t\t\t// Or the window itself (dispatched from window)\n\t\t\telement === window\n\t\t);\n\t}\n\treturn this.rootElement === element;\n}\n\n/**\n * Check whether the ID of\n * the element in 'this'\n * matches the given ID.\n *\n * IDs are case-sensitive.\n *\n * @param {string} id The ID to test against\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesId(id, element) {\n\treturn id === element.id;\n}\n\n/**\n * Short hand for off()\n * and root(), ie both\n * with no parameters\n *\n * @return void\n */\nDelegate.prototype.destroy = function () {\n\tthis.off();\n\tthis.root();\n};\n\nexport default Delegate;\n","/**\n * Shared 'internal' scope.\n */\nimport {get} from './core/settings.js';\n\n/**\n * CUID Generator\n */\nimport {api as cuid} from '../libs/browser-cuid.js';\n\n/**\n * Record of callbacks to call when a page is tracked.\n */\nconst page_callbacks = [];\n\n/**\n * Log messages to the browser console. Requires 'log' to be set on init.\n *\n * @param {*} args items to log\n * @returns {void}\n */\nfunction log(...args) {\n\tif (get('config').test && window.console) {\n\t\tfor (const arg of args) {\n\t\t\twindow.console.log(arg);\n\t\t}\n\t}\n}\n\n/**\n * Creates a logging function that logs messages to the console with a specified namespace.\n *\n * @function namedLog\n * @param {string} namespace - The namespace to be prefixed to each log message.\n * @returns {function} A function that logs messages to the console with the given namespace if the configuration allows.\n *\n * @example\n * const log = namedLog('MyNamespace');\n * log('This is a message'); \n * // Output: [MyNamespace]: This is a message\n */\nfunction namedLog(namespace) {\n\treturn function(...args) {\n\t\tif(get('config').test && window.console) {\n\t\t\twindow.console.log(`%c[${namespace}]:`, 'color: teal', ...args)\n\t\t}\n\t}\n}\n\n/**\n * Tests if variable is a certain type. Defaults to check for undefined if no type specified.\n *\n * @param {*} variable - The variable to check.\n * @param {string=} type - The type to test for. Defaults to undefined.\n *\n * @returns {boolean} - The answer for if the variable is of type.\n */\nfunction is(variable, type = 'undefined') {\n\treturn typeof variable === type;\n}\n\n/**\n * Merge objects together. Will remove undefined and null values.\n *\n * @param {object} target - The original object to merge in to.\n * @param {object} options - The object to merge into the target. If omitted, will merge target into a new empty Object.\n *\n * @returns {object} The merged object.\n */\nfunction merge(target, options) {\n\tif (!options) {\n\t\toptions = target;\n\t\ttarget = {};\n\t}\n\n\tlet name;\n\tlet src;\n\tlet copy;\n\n\t/* jshint -W089 */\n\t/* eslint guard-for-in: 0 */\n\tfor (name in options) {\n\t\tsrc = target[name];\n\t\tcopy = options[name];\n\n\t\t// Prevent never-ending loop\n\t\tif (target === copy) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Gets rid of missing values too\n\t\tif (typeof copy !== 'undefined' && copy !== null) {\n\t\t\ttarget[name] = src === Object(src) && !is(src, 'function') ? merge(src, copy) : copy;\n\t\t}\n\t}\n\t/* jshint +W089 */\n\t/* jslint forin:true */\n\n\treturn target;\n}\n\n/**\n * URL encode a string.\n *\n * @param {string} str - The string to be encoded.\n * @returns {string} The encoded string.\n */\nfunction encode(str) {\n\tif (window.encodeURIComponent) {\n\t\treturn window.encodeURIComponent(str);\n\t} else {\n\t\treturn window.escape(str);\n\t}\n}\n\n/**\n * URL decode a string.\n *\n * @param {string} str - The string to be decoded.\n * @returns {string} The decoded string.\n */\nfunction decode(str) {\n\tif (window.decodeURIComponent) {\n\t\treturn window.decodeURIComponent(str);\n\t} else {\n\t\treturn window.unescape(str);\n\t}\n}\n\n/**\n * Utility to add event listeners.\n *\n * @param {Element} element\n * @param {string} event\n * @param {EventListenerOrEventListenerObject} listener\n * @returns {void}\n */\nfunction addEvent(element, event, listener) {\n\tif (element.addEventListener) {\n\t\telement.addEventListener(event, listener, false);\n\t} else {\n\t\telement.attachEvent('on' + event, listener);\n\t}\n}\n\n/**\n * Utility for dispatching custom events from window\n *\n * @param {string} namespace\n * @param {string} eventType\n * @param {object} detail\n * @returns {void}\n */\nfunction broadcast(namespace, eventType, detail) {\n\tdetail = detail || {};\n\ttry {\n\t\twindow.dispatchEvent(new CustomEvent(namespace + '.' + eventType, {\n\t\t\tdetail: detail,\n\t\t\tbubbles: true\n\t\t}));\n\t} catch (error) {\n\t\t// empty\n\t}\n}\n\n/**\n * Listen for page tracking requests.\n *\n * @param {Function} cb - The callback to be called whenever a page is tracked.\n * @returns {void}\n */\nfunction onPage(cb) {\n\tif (is(cb, 'function') && !page_callbacks.includes(cb)) {\n\t\tpage_callbacks.push(cb);\n\t}\n}\n\n/**\n * Trigger the 'page' listeners.\n *\n * @returns {void}\n */\nfunction triggerPage() {\n\tfor (let i = 0; i < page_callbacks.length; i++) {\n\t\tpage_callbacks[i]();\n\t}\n}\n\n/**\n * Get a value from document.cookie matching the first match of the regexp you supply\n *\n * @param {RegExp} matcher - The Regex to match with\n * @returns {string} - The vale from the cookie\n */\nfunction getValueFromCookie(matcher) {\n\treturn document.cookie.match(matcher) && RegExp.$1 !== '' && RegExp.$1 !== 'null' ? RegExp.$1 : null;\n}\n\n/**\n * Filter an object to only have the properties which are listed in the `allowlist` parameter.\n *\n * @param {object} objectToFilter - An object whose props need to be filtered\n * @param {Array} allowedPropertyNames - The list of props to allow\n * @returns {object} An object containing only the allowed props\n */\nfunction filterProperties (objectToFilter, allowedPropertyNames) {\n\tconst filteredObject = {};\n\tfor (const allowedName of allowedPropertyNames) {\n\t\tif (objectToFilter[allowedName]) {\n\t\t\tfilteredObject[allowedName] = objectToFilter[allowedName];\n\t\t}\n\t}\n\treturn filteredObject;\n}\n\n/**\n * Trim strings\n *\n * @param {string} str - The string to trim.\n * @returns {string} The trimmed string.\n */\nfunction sanitise (str) {\n\treturn typeof str === 'string' ? str.trim() : str;\n}\n\n/**\n * Assign the subject value if the target properties are undefined\n *\n * @param {object} subject - assign the value\n * @param {object} target - be assigned the value\n * @returns {void}\n */\nfunction assignIfUndefined (subject, target) {\n\tfor (const prop in subject) {\n\t\tif (!target[prop]) {\n\t\t\ttarget[prop] = subject[prop];\n\t\t} else {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`You can't set a custom property called ${prop}`);\n\t\t}\n\t}\n}\n\n\n/**\n * Identify circular references in 'object', and replace them with a string representation\n * of the reference. Returns a succesfully serialised JSON string, and a list of circular\n * references which were removed.\n * \n * Inspired by https://github.com/sindresorhus/safe-stringify and \n * https://github.com/sindresorhus/decircular\n *\n * @param {*} object The object we want to stringify, and search within for circular references\n * @returns {Object: {jsonString: string, warnings: array}} The stringified object, and a warnings for each circular reference which was removed\n */\nfunction removeCircularReferences(object) {\n\n\t// WeakMaps release memory when all references are garbage-collected\n\tconst circularReferences = new WeakMap();\n\tconst paths = new WeakMap();\n\n\tconst warnings = [];\n\n\tfunction getPathFragment(parent, key) {\n\t\tif (!key) {\n\t\t\treturn '$';\n\t\t}\n\n\t\tif (Array.isArray(parent)) {\n\t\t\treturn `[${key}]`;\n\t\t}\n\n\t\treturn `.${key}`;\n\t}\n\n\tfunction formatCircularReferencesWarning(references) {\n\t\tconst paths = references.map(path => '`' + path.join('') + '`');\n\t\treturn 'Circular reference between ' + paths.join(' AND ');\n\t}\n\n\tfunction replacer(key, value) {\n\t\t// Scalars don't need to be inspected as they can't contain circular references\n\t\tif (!(value !== null && typeof value === 'object')) {\n\t\t\treturn value\n\t\t}\n\n\t\t// Record the path from the root ($) to the current object (value)\n\t\t// in order to print helpful circular reference warnings.\n\t\tconst path = [...paths.get(this) || [], getPathFragment(this, key)];\n\t\tpaths.set(value, path);\n\n\t\t// If a reference to the current value is already in the list, we have\n\t\t// a circular reference. Add the current value to the list along with its path,\n\t\t// and return a useful error string rather than the unserialisable value.\n\t\tif (circularReferences.has(value)) {\n\t\t\tconst references = [...circularReferences.get(value), path];\n\t\t\tcircularReferences.set(value, references);\n\t\t\tconst warning = formatCircularReferencesWarning(references);\n\t\t\twarnings.push(warning);\n\t\t\treturn warning;\n\t\t}\n\n\t\t// This is the first time we've seen the current value in this branch \n\t\t// of the object. Record its path from the object root.\n\t\tcircularReferences.set(value, [path]);\n\n\t\t// Recurse into the value to proactively find circular references\n\t\t// before encountering a loop.\n\t\tconst newValue = Array.isArray(value) ? [] : {};\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tnewValue[k] = replacer.call(value, k, v);\n\t\t}\n\n\t\t// All circular references to this object will have been identified,\n\t\t// so remove it from the list.\n\t\tcircularReferences.delete(value);\n\n\t\t// This branch of the object can now be safely serialised to a JSON string\n\t\treturn newValue;\n\t}\n\n\tconst jsonString = JSON.stringify(object, replacer);\n\treturn {jsonString, warnings};\n}\n\n\n/**\n * Stringify an object to JSON, removing any circular references. When circular references\n * are found, an error is thrown in a new event loop so that global error handlers can report it.\n *\n * @param {*} object The object we want to stringify, and search within for circular references\n * @returns {string} The safely stringified JSON string\n */\nfunction safelyStringifyJson(object) {\n\n\t// JSON.stringify throws on two cases:\n\t// - value contains a circular reference\n\t// - A BigInt value is encountered\n\t// Circular references are a real possibility in the way o-tracking is called (and saves a queue of \n\t// messages in a store), so we need to handle those gracefully.\n\t// \n\t// However, for performance reasons, we always attempt to do a basic JSON.stringify() first. The \n\t// recursion involved in removeCircularReferences() makes it about 20x slower to stringify a basic payload. \n\t// This performance hit will be exacerbated on slow devices (e.g. old Android phones) with lots of queued offline events.\n\ttry {\n\t\treturn JSON.stringify(object);\n\n\t// NB: error is discarded - we have more work to do in order to throw a useful message\n\t} catch (error) {\n\t\n\t\tconst {jsonString, warnings} = removeCircularReferences(object);\n\t\n\t\tif (warnings.length) {\n\t\t\t// Throw in a new event loop, as we always want to return JSON so the tracking payload is sent\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst errorMessage = \"AssertionError: o-tracking does not support circular references in the analytics data.\\n\" +\n\t\t\t\t\"Please remove the circular references in the data.\\n\" +\n\t\t\t\t\"Here are the paths in the data which are circular:\\n\" +\n\t\t\t\twarnings.join('\\n');\n\t\t\t\tthrow new Error(errorMessage);\n\t\t\t});\n\t\t}\n\t\n\t\treturn jsonString;\n\t}\n\n\n};\n\n/**\n * Find out whether two objects are deeply equal to each other.\n *\n * @param {*} a\n * @param {*} b\n * @returns {boolean} - true if the two arguments are deeply equal\n */\nfunction isDeepEqual(a, b) {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (\n\t\ta &&\n\t\tb &&\n\t\ttypeof a === \"object\" &&\n\t\ttypeof b === \"object\"\n\t) {\n\t\tif (a.constructor !== b.constructor) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (Array.isArray(a)) {\n\t\t\tconst length = a.length;\n\t\t\tif (length !== b.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\t\tif (!isDeepEqual(a[i], b[i])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tif (a.constructor === RegExp) {\n\t\t\treturn (\n\t\t\t\ta.source === b.source && a.flags === b.flags\n\t\t\t);\n\t\t}\n\t\tif (a.valueOf !== Object.prototype.valueOf) {\n\t\t\treturn a.valueOf() === b.valueOf();\n\t\t}\n\t\tif (a.toString !== Object.prototype.toString) {\n\t\t\treturn a.toString() === b.toString();\n\t\t}\n\n\t\tconst keys = Object.keys(a);\n\t\tconst length = keys.length;\n\t\tif (length !== Object.keys(b).length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(b, keys[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\tconst key = keys[i];\n\n\t\t\tif (!isDeepEqual(a[key], b[key])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n\nexport {\n\tlog,\n\tnamedLog,\n\tis,\n\tis as isUndefined,\n\tmerge,\n\tencode,\n\tdecode,\n\tcuid as guid,\n\taddEvent,\n\tbroadcast,\n\tonPage,\n\ttriggerPage,\n\tgetValueFromCookie,\n\tsanitise,\n\tassignIfUndefined,\n\tfilterProperties,\n\tremoveCircularReferences,\n\tsafelyStringifyJson,\n\tisDeepEqual\n};\n","import { ComponentPath } from \"./path\";\n\nexport const LogLevel = Object.freeze({\n DEBUG: 0,\n INFO: 1,\n WARN: 2,\n ERROR: 3,\n TEST: 4,\n DEFAULT: 2,\n});\n\nconst LOG_PREFIX = \"CCC:\";\n\nexport function convertStringLogLevel(value: string | null) {\n const level = value?.toLowerCase();\n\n if (level === \"debug\") {\n return LogLevel.DEBUG;\n }\n\n if (level === \"info\") {\n return LogLevel.INFO;\n }\n\n if (level === \"warn\") {\n return LogLevel.WARN;\n }\n\n if (level === \"error\") {\n return LogLevel.ERROR;\n }\n\n if (level === \"test\") {\n return LogLevel.TEST;\n }\n\n return LogLevel.DEFAULT;\n}\n\nexport class Logger {\n public level: number;\n public component?: ComponentPath;\n\n constructor(\n {\n level = LogLevel.DEFAULT,\n component,\n }: { level: number; component?: ComponentPath } = {\n level: LogLevel.DEFAULT,\n }\n ) {\n this.level = localStorage?.getItem(\"CCC_LOG_LEVEL\")\n ? convertStringLogLevel(localStorage.getItem(\"CCC_LOG_LEVEL\"))\n : level;\n this.component = component;\n }\n\n debug(...args: any[]) {\n if (this.level <= LogLevel.DEBUG) {\n console.info(LOG_PREFIX, ...args, this.component);\n }\n }\n\n log = this.debug;\n\n info(...args: any[]) {\n if (this.level <= LogLevel.INFO) {\n console.info(LOG_PREFIX, ...args, this.component);\n }\n }\n\n warn(...args: any[]) {\n if (this.level <= LogLevel.WARN) {\n console.warn(LOG_PREFIX, ...args, this.component);\n }\n }\n\n error(...args: any[]) {\n if (this.level <= LogLevel.ERROR) {\n console.error(LOG_PREFIX, ...args, this.component);\n }\n }\n\n setLogLevel(level: string | number | null) {\n if (localStorage?.getItem(\"CCC_LOG_LEVEL\")) {\n this.level = convertStringLogLevel(localStorage.getItem(\"CCC_LOG_LEVEL\"));\n } else if (typeof level === \"number\") {\n this.level = level;\n } else {\n this.level = convertStringLogLevel(level);\n }\n }\n}\n","// Trace the element and all of its parents, collecting properties as we go\nimport {\n sanitise,\n assignIfUndefined,\n} from \"@financial-times/o-tracking/src/javascript/utils\";\n\ntype PropMap = { [k: string]: any };\n// For a given container element, get the number of elements that match the\n// original element (siblings); and the index of the original element (position).\nconst getSiblingsAndPosition = (\n el: Element | null,\n originalEl: Element,\n selector: string\n) => {\n const siblings = Array.from(el?.querySelectorAll(selector) ?? []);\n const position = siblings.findIndex((item) => item === originalEl);\n if (position === -1) {\n return;\n }\n return {\n siblings: siblings.length,\n position,\n };\n};\n\nconst elementPropertiesToCollect = [\n \"nodeName\",\n \"className\",\n \"id\",\n \"href\",\n \"text\",\n \"role\",\n];\n// Get all (sanitised) properties of a given element.\nconst getAllElementProperties = (element: any) => {\n const properties: PropMap = {};\n for (const property of elementPropertiesToCollect) {\n const value =\n element[property] ||\n element.getAttribute(property) ||\n element.hasAttribute(property);\n if (value !== undefined) {\n if (typeof value === \"boolean\") {\n properties[property] = value;\n } else {\n properties[property] = sanitise(value);\n }\n }\n }\n\n return properties;\n};\n\nconst parseRawValue = (rawValue: string) => {\n try {\n const parsedValue = JSON.parse(rawValue);\n const type = Object.prototype.toString.call(parsedValue);\n const isJSON = type === \"[object Object]\" || type === \"[object Array]\";\n\n return [isJSON, parsedValue];\n } catch (error) {\n return [false, null];\n }\n};\n\nconst getAttributeValue = (rawValue: string) => {\n const [isJSON, value] = parseRawValue(rawValue);\n\n return isJSON ? value : rawValue;\n};\n\n// Get some properties of a given element.\nconst getDomPathProps = (attrs: Attr[], props: PropMap) => {\n // Collect any attribute that matches given strings.\n attrs\n .filter((attribute) =>\n attribute.name.match(/^data-trackable|^data-o-|^aria-/i)\n )\n .forEach((attribute) => {\n props[attribute.name] = attribute.value;\n });\n\n return props;\n};\n\n// Get only the custom data-trackable-context-? properties of a given element\nconst getContextProps = (\n attrs: Attr[],\n props: PropMap,\n isOriginalEl: boolean\n) => {\n const customProps: { [k: string]: any } = {};\n\n // for the original element collect properties like className, nodeName\n if (isOriginalEl) {\n elementPropertiesToCollect.forEach((name) => {\n if (typeof props[name] !== \"undefined\" && name !== \"id\") {\n customProps[name] = props[name];\n }\n });\n }\n\n // Collect any attribute that matches given strings.\n attrs\n .filter((attribute) => attribute.name.match(/^data-trackable-context-/i))\n .forEach((attribute) => {\n customProps[attribute.name.replace(\"data-trackable-context-\", \"\")] =\n getAttributeValue(attribute.value);\n });\n\n return customProps;\n};\n\nexport function getTrace(el: Element, rootEl: Element) {\n const originalEl = el;\n const selector = originalEl?.getAttribute(\"data-trackable\")\n ? `[data-trackable=\"${originalEl.getAttribute(\"data-trackable\")}\"]`\n : originalEl?.nodeName;\n const trace = [];\n const customContext = {};\n while (el && el !== rootEl) {\n const props = getAllElementProperties(el);\n const attrs = Array.from(el.attributes);\n let domPathProps = getDomPathProps(attrs, props);\n\n // If the element happens to have a data-trackable attribute, get the siblings\n // and position of the element (relative to the current element).\n if (domPathProps[\"data-trackable\"]) {\n domPathProps = Object.assign(\n domPathProps,\n getSiblingsAndPosition(el, originalEl, selector)\n );\n }\n\n trace.push(domPathProps);\n\n const contextProps = getContextProps(attrs, props, el === originalEl);\n\n assignIfUndefined(contextProps, customContext);\n\n el = el.parentNode as Element;\n }\n return { trace, customContext };\n}\n","import Delegate from \"ftdomdelegate/main\";\n\nimport {\n sanitise,\n assignIfUndefined,\n} from \"@financial-times/o-tracking/src/javascript/utils\";\nimport { Logger } from \"./logger\";\nimport { getTrace } from \"./get-trace\";\n\nconst eventPropertiesToCollect = [\"ctrlKey\", \"altKey\", \"shiftKey\", \"metaKey\"];\n\nclass Tracking {\n cccId: string;\n cccName: string;\n subtype: string;\n teamName: string;\n shadowRoot: ShadowRoot | null;\n category: string;\n elements: string | string[];\n isInitialised: boolean;\n log: Logger;\n shadowDelegate: typeof Delegate;\n\n constructor({\n id = \"00000000-0000-0000-0000-000000000000\",\n name = \"ccc-component\",\n subtype = \"interactive\",\n teamName = \"djd\",\n shadowRoot = null,\n category = \"cta\",\n elements = 'a, button, input, [role=\"button\"]',\n logger,\n }: {\n id?: string;\n name: string;\n subtype: string;\n teamName?: string;\n shadowRoot: ShadowRoot | null;\n category?: string;\n elements?: string | string[];\n logger: Logger;\n }) {\n this.cccId = id;\n this.cccName = name;\n this.subtype = subtype;\n this.teamName = teamName;\n this.shadowRoot = shadowRoot;\n this.category = category;\n this.elements = elements;\n this.isInitialised = false;\n this.log = logger ?? new Logger();\n }\n\n // Get properties for the event (as opposed to properties of the clicked element)\n getEventProperties(event: any) {\n const eventProperties: { [k: string]: any } = {};\n for (const property of eventPropertiesToCollect) {\n if (event[property]) {\n try {\n eventProperties[property] = sanitise(event[property]);\n } catch (e) {\n this.log.info(e);\n }\n }\n }\n return eventProperties;\n }\n\n // Controller for handling click events\n handleClickEvent(\n eventData: { action: string; category: string },\n root: Element,\n ) {\n return (clickEvent: Event, clickElement: HTMLElement) => {\n const context: any = this.getEventProperties(clickEvent);\n const { trace, customContext } = getTrace(clickElement, root);\n context.custom =\n clickElement.dataset && clickElement.dataset.custom\n ? JSON.parse(clickElement.dataset.custom)\n : null;\n context.domPathTokens = trace;\n context.component = {\n id: this.cccId,\n name: this.cccName,\n type: \"custom-code-component\",\n subtype: this.subtype,\n };\n context.teamName = this.teamName;\n context.url = document.URL;\n\n assignIfUndefined(customContext, context);\n\n context.method = \"ftCustomAnalytics\";\n eventData = { ...eventData, ...context };\n\n // send spoor event\n document.body.dispatchEvent(\n new CustomEvent(\"oTracking.event\", {\n detail: eventData,\n bubbles: true,\n composed: true,\n }),\n );\n };\n }\n\n sendSpoorEvent(triggerAction: any, extraDetail: any) {\n const eventData = {\n category: \"component\",\n action: \"act\",\n component: {\n id: this.cccId,\n name: this.cccName,\n type: \"custom-code-component\",\n subtype: this.subtype,\n },\n teamName: this.teamName,\n trigger_action: triggerAction,\n custom: extraDetail,\n method: \"ftCustomAnalytics\",\n };\n\n // send spoor event\n document.body.dispatchEvent(\n new CustomEvent(\"oTracking.event\", {\n detail: eventData,\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n init(id: string) {\n if (!this.isInitialised) {\n this.isInitialised = true;\n this.cccId = id ? id : this.cccId;\n\n const eventData = {\n action: \"click\",\n category: this.category,\n };\n\n const root = this.shadowRoot?.querySelector(\"[data-component-root]\");\n\n if (root) {\n this.shadowDelegate = new Delegate(root);\n this.shadowDelegate.on(\n \"click\",\n this.elements,\n this.handleClickEvent(eventData, root),\n true,\n );\n }\n }\n }\n\n destroy() {\n this.shadowDelegate?.off();\n }\n}\n\nexport default Tracking;\n","import { CCCError } from \"./errors\";\n\nexport type ComponentPathType = {\n org: string;\n repo: string;\n name: string;\n versionRange: string;\n};\nexport class ComponentPath {\n org: string = \"local\";\n repo: string = \"dev\";\n name: string;\n versionRange: string;\n\n constructor(path?: ComponentPathType | string) {\n const { org, repo, name, versionRange } = isValidComponentPathObject(path)\n ? path\n : ComponentPath.fromString(path);\n if (org) this.org = org;\n if (repo) this.repo = repo;\n this.name = name;\n this.versionRange = versionRange;\n }\n\n set path(path: ComponentPathType | string) {\n const { org, repo, name, versionRange } = isValidComponentPathObject(path)\n ? path\n : ComponentPath.fromString(path);\n this.org = org;\n this.repo = repo;\n this.name = name;\n this.versionRange = versionRange;\n }\n\n get path(): string {\n return `${this.org}/${this.repo}@${this.versionRange}/${this.name}`;\n }\n\n get isValid(): boolean {\n return [this.org, this.repo, this.name].every(\n (value) => value !== \"unknown\"\n );\n }\n\n toString(): string {\n return this.path;\n }\n\n static fromString(p?: string | null, v?: string | null): ComponentPath {\n const path = p ?? \"unknown/unknown/unknown\";\n\n const [name, repo, org] = path\n .replace(/@[^\\/]+/, \"\")\n .split(\"/\")\n .reverse();\n\n const versionRange =\n v ??\n path\n .match(/@[^\\/]+/)\n ?.toString()\n .replace(\"@\", \"\") ??\n \"unknown\";\n\n if (repo && !versionRange) throw new CCCError(\"No version specified\");\n\n return new ComponentPath({ org, repo, name, versionRange });\n }\n}\n\nexport type DetailType = {\n component: ComponentPath;\n source?: string;\n cause?: string;\n error?: Error;\n};\n\nexport function isValidComponentPathObject(\n value: unknown\n): value is ComponentPathType {\n if (typeof value === \"object\" && value !== null) {\n return \"org\" in value && \"repo\" in value && \"name\" in value;\n }\n\n return false;\n}\n","/**\n * This is the base CCC component error class. These are raised when the component being loaded errors\n */\n\nimport { ComponentPath, DetailType, isValidComponentPathObject } from \"./path\";\n\nexport class CCCError extends Error {\n component: ComponentPath | null;\n source?: string;\n errors?: Error[];\n constructor(message: string | null, detail?: DetailType) {\n if (!detail && message) {\n super(message);\n this.component = null;\n } else if (typeof detail?.component === \"string\") {\n super(\n message ??\n `${detail.cause ?? \"Unknown error\"} in ${detail.component} imported from ${detail.source ?? \"an undefined source\"}.`\n );\n\n this.component = ComponentPath.fromString(detail.component);\n } else if (isValidComponentPathObject(detail?.component)) {\n super(\n message ??\n `${detail.cause ?? \"Unknown error\"} in ${detail.component.org}/${detail.component.repo}/${detail.component.name}@${detail.component.versionRange} imported from ${detail.source ?? \"an undefined source\"}.`\n );\n this.component = new ComponentPath(detail.component);\n } else {\n super(\n `${detail?.cause ?? \"Unknown error\"} in unknown component imported from ${detail?.source ?? \"unknown source\"}.`\n );\n this.component = null;\n }\n\n this.source = detail?.source ?? \"unknown source\";\n this.errors = [];\n if (detail?.error) {\n this.errors?.push(detail?.error);\n }\n if (Error.captureStackTrace) {\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n Error.captureStackTrace(this, CCCError);\n }\n\n this.name = \"CCCError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur during the import of the CCC component app\n */\nexport class CCCImportError extends CCCError {\n constructor(message: string, detail: DetailType) {\n super(message, { ...detail, cause: \"Import error\" });\n this.name = \"CCCImportError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur during the rendering of the CCC component app\n */\nexport class CCCRenderError extends CCCError {\n constructor(message: string, detail: DetailType) {\n super(message, { ...detail, cause: \"Render error\" });\n this.name = \"CCCRenderError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur as a result of the CCC component app timing out\n */\nexport class CCCTimeoutError extends CCCError {\n constructor(detail: DetailType) {\n super(null, { ...detail, cause: \"Timeout error\" });\n this.name = \"CCCTimeoutError\";\n }\n}\n","import { ComponentPath } from \"./path\";\n\nexport class CCCEvent extends Event {\n component: ComponentPath;\n source?: string;\n static eventType = \"ccc:event\";\n\n constructor(\n eventType: string = CCCEvent.eventType,\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(eventType, {\n bubbles: true,\n cancelable: false,\n composed: true,\n ...opts,\n });\n this.component = detail.component;\n this.source = detail.source;\n }\n}\n\nexport class CCCConnectedEvent extends CCCEvent {\n static eventType = \"ccc:connected\";\n\n constructor(\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(CCCConnectedEvent.eventType, detail, opts);\n }\n}\n\nexport class CCCReadyEvent extends CCCEvent {\n static eventType = \"ccc:ready\";\n\n constructor(\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(CCCReadyEvent.eventType, detail, opts);\n }\n}\n\nexport class CCCViewportEvent extends CCCEvent {\n static eventType = \"ccc:viewport\";\n intersecting = false;\n entry?: IntersectionObserverEntry;\n\n constructor(\n detail: {\n component: ComponentPath;\n source?: string;\n intersecting: boolean;\n entry?: IntersectionObserverEntry;\n },\n opts?: EventInit\n ) {\n super(CCCViewportEvent.eventType, detail, opts);\n this.intersecting = detail.intersecting;\n this.entry = detail.entry;\n }\n}\n","/**\n * Used to convert camelCase to kebab-case\n * @param str\n * @returns\n */\nexport const kebabize = (str: string) =>\n str.replace(\n /[A-Z]+(?![a-z])|[A-Z]/g,\n ($, ofs) => (ofs ? \"-\" : \"\") + $.toLowerCase()\n );\n\n/**\n * Checks if the provided host is part of the allowed test environments.\n *\n * @param host - The hostname to check.\n * @returns True if the hostname is a safe test environment, false otherwise.\n */\nexport function isSafeTestEnv(host: string | undefined) {\n return isAllowed([\n 'localhost',\n 'local.ft.com',\n /^.*\\.apps\\.in\\.ft\\.com$/,\n ], host);\n}\n\n/**\n * Checks if the current window location hostname is considered a local environment.\n *\n * @returns True if the hostname is local, false otherwise.\n */\nexport function isLocalEnv() {\n return isAllowed([\n 'localhost',\n 'local.ft.com',\n /^.*\\.in\\.ft\\.com$/,\n ], window.location.hostname);\n}\n\n/**\n * Checks if the current window location host is one of the Spark environments.\n *\n * @returns True if the host is spark.ft.com or spark-staging.ft.com, false otherwise.\n */\nexport function isSparkEnv() {\n return isAllowed([\n 'spark.ft.com',\n 'spark-staging.ft.com',\n ], window.location.host);\n}\n\n/**\n * Checks if the given hostname is in the provided allowlist.\n *\n * @param allowlist - A list of allowed hostnames or RegExp matchers.\n * @param hostname - The hostname to validate.\n * @returns True if the hostname matches any item in the allowlist, false otherwise.\n */\nexport function isAllowed(allowlist: (string|RegExp)[], hostname: string | undefined) {\n if (!hostname) return false;\n return allowlist.some(item => {\n if (typeof item === 'string') {\n return item === hostname;\n }\n return item.test(hostname);\n });\n} \n","import { isLocalEnv, isSafeTestEnv, isSparkEnv } from \"./util\";\n\n/**\n * Assigns a test URL based on the provided testEnv value.\n *\n * @param testEnv - A string indicating test environment setting\n * @returns A `URL` object if valid and safe, or `undefined` if invalid.\n */\nexport function assignTestURL(testEnv: string | null): URL | undefined {\n if (testEnv === null) {\n return;\n }\n\n let testUrl;\n const defaultTestUrl = new URL(\"http://localhost:5173\");\n\n try {\n if (typeof testEnv === \"string\") {\n if (\n (testEnv === \"\" || testEnv.toLowerCase() === \"true\") &&\n isLocalEnv()\n ) {\n testUrl = defaultTestUrl;\n } else {\n const hasProtocol =\n testEnv.startsWith(\"http://\") || testEnv.startsWith(\"https://\");\n testUrl = hasProtocol ? new URL(testEnv) : undefined;\n\n // Prevent script injection\n if (testUrl && !isSafeTestEnv(testUrl?.hostname)) {\n throw new Error(\"Unsafe testing host override\");\n }\n }\n } else if (isSparkEnv()) {\n testUrl = defaultTestUrl;\n }\n } catch (_) {\n return testUrl;\n }\n\n return testUrl;\n}\n\n/**\n * Checks whether the given test component exists on local dev server\n *\n * @param testUrl - The test environment URL to check.\n * @returns A promise that resolves to true if Vite is running, false otherwise.\n */\nexport async function useComponentTestEnv(\n componentName: string,\n testUrl?: URL\n): Promise<boolean> {\n if (!testUrl) {\n return false;\n }\n\n const localDevOnline = fetch(\n new URL(`src/${componentName}/config.yaml`, testUrl),\n {\n method: \"HEAD\",\n }\n )\n .then(() => true)\n .catch(() => false);\n\n return localDevOnline;\n}\n","/**\n * @file\n * Main component definition for custom-code-component\n */\n\nimport type { ContentTree } from \"@financial-times/content-tree\";\nimport type { BaseRenderer } from \"../../ccc-sdk/src/renderers/BaseRenderer\";\nimport Tracking from \"./tracking\";\nimport { Logger, LogLevel } from \"./logger\";\nimport {\n CCCError,\n CCCImportError,\n CCCRenderError,\n CCCTimeoutError,\n} from \"./errors\";\nimport { CCCConnectedEvent, CCCReadyEvent, CCCViewportEvent } from \"./events\";\nimport { ComponentPath } from \"./path\";\nimport { kebabize } from \"./util\";\nimport { assignTestURL, useComponentTestEnv } from \"./environment\";\nimport styles from \"./custom-code-component.css?inline\";\n\nexport class FTCustomCodeComponent extends HTMLElement {\n /**\n * The component renderer, resolved from dynamic import\n */\n app?: typeof BaseRenderer.prototype.render;\n\n /**\n * Set whether component is \"open\" or \"closed\". Defaults to \"open\".\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#mode\n */\n mode: \"closed\" | \"open\" = \"open\";\n\n /**\n * Reserved attributes we don't pass to the child component\n */\n RESERVED_ATTRS = new Set([\n \"iframe\",\n \"path\",\n \"version\",\n \"data-component-props\",\n \"data-asset-type\",\n \"shadow-open\",\n \"env\",\n \"load-timeout\",\n ]);\n\n /**\n * URI of component module for CCC webcomponent to load\n */\n source?: string;\n\n /**\n * OTracking config\n */\n tracking?: Tracking;\n\n /**\n * Alternative base URL, used for testing\n */\n testUrl?: URL;\n\n /**\n * ComponentPath instance with `org`, `repo`, `name` and `versionRange` attributes\n */\n component = new ComponentPath();\n\n /**\n * Logger instance. Set log level using `this.logger.setLogLevel(string|number|null)`.\n */\n logger: Logger;\n\n /**\n * Abort controller used to abort async connectedCallback functionality when disconnectedCallback is called`.\n */\n ac: AbortController | null = null;\n\n /**\n * IntersectionObserver that dispatches CCCViewportEvents\n */\n observer = new IntersectionObserver((entries) => {\n this.logger.debug(\"Intersection Observer callback\", { entries });\n entries.forEach((entry) => {\n this.dispatchEvent(\n new CCCViewportEvent({\n component: this.component,\n source: this.source,\n intersecting: entry.isIntersecting,\n entry,\n }),\n );\n });\n });\n\n /**\n * Custom Element constructor.\n *\n * n.b., attributes and ShadowDOM aren't available in custom element constructors.\n * Use connectedCallback() and other lifecycle methods if you want to eg. this.getAttribute()\n */\n constructor() {\n super();\n this.logger = new Logger();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n\n try {\n const internals = supportsDeclarative && this.attachInternals();\n } catch (e) {\n this.logger.error(e);\n }\n }\n\n /**\n * connectedCallback() CE lifecycle callback\n *\n * Called whenever a <custom-code-component> element is mounted to the DOM.\n */\n async connectedCallback() {\n try {\n const path = this.getAttribute(\"path\");\n const versionRange = this.getAttribute(\"version\");\n this.component = ComponentPath.fromString(path, versionRange);\n this.logger.component = this.component;\n this.logger.setLogLevel(this.getAttribute(\"log\"));\n this.logger.debug(\"connectedCallback\");\n this.ac?.abort();\n this.ac = new AbortController();\n this.app = await this.load(this.ac.signal);\n this.mount();\n this.initTracking();\n } catch (e) {\n if (e instanceof Error) {\n requestAnimationFrame(() => {\n this.emitError(e);\n });\n }\n\n this.unmount(e as Error);\n }\n }\n\n /**\n * Error handler. Decorates errors for easier ingestion.\n *\n * @param error\n */\n emitError(error: Error) {\n this.logger.debug(\"emitError\", { error });\n if (error instanceof CCCError) {\n this.dispatchEvent(\n new ErrorEvent(\"ccc:error\", {\n bubbles: true,\n cancelable: false,\n composed: true,\n error,\n message: error.message,\n }),\n );\n } else {\n // Wrap original error with generic CCC error class\n const wrappedError = new CCCError(error.message, {\n component: this.component,\n error: error,\n });\n\n this.dispatchEvent(\n new ErrorEvent(\"ccc:error\", {\n bubbles: true,\n cancelable: false,\n composed: true,\n error: wrappedError,\n message: wrappedError.message,\n }),\n );\n }\n }\n\n /**\n * disconnectedCallback() CE lifecycle event.\n *\n * Called when a <custom-code-component> element is removed from DOM.\n */\n disconnectedCallback() {\n this.ac?.abort();\n this.logger.debug(\"disconnectedCallback\");\n const path = this.getAttribute(\"path\");\n this.destroyTracking();\n this.logger.info(`<custom-code-component:${path}> disconnected`);\n this.observer.disconnect();\n }\n\n /**\n * MessageChannel interface.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel\n */\n channel = new MessageChannel();\n\n /**\n * MessageChannel postMessage callback\n *\n * @param e\n */\n onmessage(e?: any) {\n this.logger.debug(\"onmessage\", { event: e });\n }\n\n /**\n * This error handler is called by the child component on e.g. unrecoverable error.\n * It then calls unmount(), which restores the fallback.\n *\n * @param e\n */\n onunmount(e: Error) {\n this.logger.debug(\"onunmount\", { error: e });\n if (e instanceof Error) {\n const renderError = new CCCRenderError(e.message, {\n error: e,\n component: this.component,\n });\n requestAnimationFrame(() => {\n this.emitError(renderError);\n this.unmount(renderError);\n });\n }\n }\n\n /**\n * onready event callback.\n * Called by mount() after kicking off initial component render.\n *\n * @param app\n */\n async onready(app: Promise<void>) {\n try {\n await app;\n this.logger.debug(\"onready\", { app });\n this.dispatchEvent(\n new CCCReadyEvent({\n component: this.component,\n source: this.source,\n }),\n );\n\n this.dataset.cccReady = \"true\";\n delete this.dataset.cccError;\n\n this.observer.observe(this);\n } catch (e) {\n this.logger.debug(\"onready caught error\", { error: e });\n if (e instanceof Error) {\n const renderError = new CCCRenderError(e.message, {\n error: e,\n component: this.component,\n });\n requestAnimationFrame(() => {\n this.emitError(renderError);\n this.unmount(renderError);\n });\n }\n }\n }\n\n /**\n * MessageChannel postMessage handler.\n * This can be used for inter-CCC communication.\n * @param event\n */\n postMessage(event: any) {\n this.logger.debug(\"postmessage\", { event });\n this.channel.port1.postMessage(event);\n }\n\n /**\n * Initial mounting behaviour.\n *\n * Attaches ShadowDOM if needed, dispatches ccc:connected event, adds component base styles,\n * generates fallback template element if one doesn't exist already, initialises tracking,\n * then kicks off component rendering. Passes component render promise to onready().\n *\n * @param prerendered\n */\n mount(prerendered?: ShadowRoot | null) {\n this.logger.debug(\"mount\", prerendered);\n try {\n this.mode =\n this.getAttribute(\"shadow-open\") == \"false\" ? \"closed\" : \"open\";\n if (this.component) {\n if (!this.app) {\n throw new Error(\"CCC mounted without App\");\n }\n\n const ssr = this.shadowRoot !== null;\n const shadow =\n this.shadowRoot ?? this.attachShadow({ mode: this.mode });\n\n this.dispatchEvent(\n new CCCConnectedEvent({\n component: this.component,\n source: this.source,\n }),\n );\n // Add global CCC styles if not already present in shadow DOM.\n if (\n !shadow.querySelector('link[href~=\"custom-code-component.css\"]') &&\n !shadow.adoptedStyleSheets.length\n ) {\n if (!window.CCC_LAYOUT_STYLESHEET) {\n this.logger.debug(\"mount generating CCC_LAYOUT_STYLESHEET\");\n window.CCC_LAYOUT_STYLESHEET = new CSSStyleSheet();\n window.CCC_LAYOUT_STYLESHEET.replaceSync(styles);\n }\n shadow.adoptedStyleSheets = [window.CCC_LAYOUT_STYLESHEET];\n }\n\n if (!ssr) {\n this.logger.debug(\"mount generating fallback template\");\n const template = document.createElement(\"template\");\n template.innerHTML = \"<div data-component-root><slot></slot></div>\";\n this.appendChild(template);\n shadow.appendChild(template.content.cloneNode(true));\n }\n\n const data = JSON.parse(this.getAttribute(\"data-component-props\")!);\n\n const extraProps = Object.fromEntries(\n [...this.attributes]\n .filter(\n (attribute) =>\n !this.RESERVED_ATTRS.has(attribute.name) &&\n !attribute.name.startsWith(\"data-\"),\n )\n .map((attribute) => [attribute.name, attribute.value]),\n );\n\n // Create tracking instance\n this.tracking = new Tracking({\n name: this.component?.toString(),\n subtype: \"interactive\",\n teamName: \"djd\",\n shadowRoot: this.shadowRoot,\n logger: this.logger,\n });\n\n if (!data && Object.keys(extraProps).length > 0) {\n this.logger.warn(\n `CCC ${this.component.toString()}: passing component settings as webcomponent attributes is %cDEPRECATED`,\n \"font-weight: bold\",\n \" and will be removed in v3.\",\n );\n this.logger.warn(\n `Please use the %cdata-component-props`,\n \"text-decoration: underline;\",\n \" attribute instead.\",\n );\n }\n\n const { onmessage, ready = Promise.resolve() } =\n this.app(\n shadow,\n {\n ...(data ?? extraProps),\n log: this.logger,\n data: data ?? extraProps,\n port: this.channel.port2,\n tracking: this.tracking,\n prerendered: !!prerendered,\n children: this.children,\n },\n ssr,\n this.onunmount.bind(this),\n ) || {};\n\n if (onmessage) this.onmessage = onmessage;\n\n this.onready(ready);\n }\n } catch (err) {\n this.logger.info(\n `<custom-code-component> uncaught error during mount from ${this.component?.toString()}`,\n );\n this.logger.error(err);\n\n throw err;\n }\n }\n\n /**\n * Called in top-level error handler or by child component on unhandled error.\n * Replace shadow root with either <slot> or template[data-component-fallback]\n * slot on failure\n *\n * @param e\n */\n unmount(e: Error) {\n this.logger.debug(\"unmount\", { error: e });\n\n const template =\n this.querySelector<HTMLTemplateElement>(\n \"template[data-component-fallback]\",\n ) ?? this.querySelector<HTMLTemplateElement>(\"template\");\n\n if (template) {\n this.logger.debug(\"unmount replacing shadowRoot with fallback\");\n this.shadowRoot?.replaceChildren(template.content.cloneNode(true));\n }\n\n if (!this.dataset.cccError)\n this.dataset.cccError = kebabize(e.name.replace(\"CCC\", \"\"));\n\n delete this.dataset.cccReady;\n\n this.observer.disconnect();\n }\n\n /**\n * Asynchronously loads the CCC child component.\n *\n * @returns Promise resolving to component renderer function\n */\n async load(signal: AbortSignal) {\n this.logger.debug(\"load\");\n\n if (!this.component.isValid) {\n throw new Error(\"No path found\");\n }\n\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n const timeout = Number(this.getAttribute(\"load-timeout\") || 10000);\n const testEnv = this.getAttribute(\"test-env\");\n this.testUrl = assignTestURL(testEnv);\n const isTestEnv = await useComponentTestEnv(\n this.component.name,\n this.testUrl,\n );\n\n // id querystring necessary to multiple allow components with the same source (same name and version number) to appear on the page correctly\n const id = this.getAttribute(\"id\");\n\n if (isTestEnv && this.testUrl) {\n this.logger.debug(\"load adding Vite scripts\");\n this.injectViteScripts();\n }\n\n this.source = isTestEnv\n ? `${this.testUrl?.origin}/src/${this.component.name}/index.jsx?id=${id}`\n : `https://www.ft.com/__component/${this.component.org}/${this.component.repo}${\n componentVersionRange ? `@${componentVersionRange}` : \"@latest\"\n }/${this.component.name}/${this.component.name}.js?id=${id}`;\n\n try {\n return await new Promise<typeof BaseRenderer.prototype.render>(\n (resolve, reject) => {\n signal.throwIfAborted();\n const to = setTimeout(() => {\n this.logger.error(\"CCC import timeout error\");\n reject(\n new CCCTimeoutError({\n component: this.component!,\n source: this.source,\n }),\n );\n }, Number(timeout));\n\n if (this.source) {\n import(/* webpackIgnore: true */ this.source /* @vite-ignore */)\n .then(({ default: componentRenderFunction }) => {\n if (componentRenderFunction) {\n clearTimeout(to);\n resolve(componentRenderFunction);\n } else\n throw new CCCImportError(\n \"No component renderer default export found\",\n {\n component: this.component!,\n source: this.source,\n },\n );\n })\n .catch((e) => {\n clearTimeout(to);\n this.logger.error(e);\n if (e instanceof Error && !(e instanceof CCCImportError)) {\n reject(\n new CCCImportError(e.message, {\n component: this.component!,\n source: this.source,\n }),\n );\n } else {\n reject(e);\n }\n });\n } else {\n clearTimeout(to);\n throw new CCCImportError(`Unable to mount ${path}`, {\n component: this.component!,\n source: this.source,\n });\n }\n\n signal.addEventListener(\n \"abort\",\n () => {\n // Stop the main operation\n // Reject the promise with the abort reason.\n reject(signal.reason);\n },\n { once: true },\n );\n },\n );\n } catch (err) {\n this.logger.error(\n `<custom-code-component> error during import from ${path}@${componentVersionRange}`,\n );\n\n throw err;\n }\n }\n\n /**\n * Initialises OTracking\n */\n initTracking = () => {\n this.logger.debug(\"initTracking\", { cccId: this.id });\n try {\n this.tracking?.init(this.id);\n } catch (e) {\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n this.logger.info(\n `Error initialising tracking on <custom-code-component> ${path}@${componentVersionRange}`,\n );\n this.logger.error(e);\n }\n };\n\n /**\n * Destroys OTracking to avoid duplicate events\n */\n destroyTracking = () => {\n this.logger.debug(\"destroyTracking\", { cccId: this.id });\n try {\n this.tracking?.destroy();\n } catch (e) {\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n this.logger.info(\n `Error destroying tracking on <custom-code-component> ${path}@${componentVersionRange}`,\n );\n this.logger.error(e);\n }\n };\n\n /**\n * Injects Vite HMR scripts during dev environment usage\n */\n injectViteScripts = () => {\n if (document.querySelector('script[name=\"ccc-sdk-react-preamble\"]')) return;\n\n const preambleScript = document.createElement(\"script\");\n preambleScript.type = \"module\";\n preambleScript.setAttribute(\"name\", \"ccc-sdk-react-preamble\");\n\n preambleScript.textContent = `\n import RefreshRuntime from \"${this.testUrl?.origin}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n `.trim();\n document.head.appendChild(preambleScript);\n\n const viteClientScript = document.createElement(\"script\");\n viteClientScript.type = \"module\";\n viteClientScript.src = `${this.testUrl?.origin}/@vite/client`;\n document.head.appendChild(viteClientScript);\n };\n\n /**\n * Called whenever the <custom-code-component>'s attributes are changed.\n * Currently only used to dynamically set log level.\n *\n * @param name\n * @param oldValue\n * @param newValue\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n this.logger.debug(\"attributeChangedCallback lifecycle method\", {\n name,\n oldValue,\n newValue,\n });\n\n switch (name) {\n case \"log\": {\n this.logger.setLogLevel(newValue);\n }\n }\n }\n}\n\nexport interface CustomCodeComponent extends ContentTree.Node {\n type: \"CustomCodeComponent\";\n path: string;\n versionRange: string;\n altText: string;\n lastModified: string;\n fallbackImage?: ContentTree.Image;\n displayFallbackText: boolean;\n layout: \"in-line\" | \"mid-grid\" | \"full-grid\" | \"full-bleed\";\n /* prettier-ignore */\n attributes: {\n [key: string]: string | boolean | undefined;\n } | { children?: CustomCodeComponent | Array<CustomCodeComponent> };\n}\n\nexport type { FTCustomCodeComponent as CCCHTMLElement };\n"],"names":["Delegate","root","listenerMap","eventType","selector","handler","useCapture","matcher","matcherParam","matchesTag","matchesId","matchesRoot","i","listener","listenerList","singleEventType","event","l","type","phase","returned","target","eventIgnore","toFire","ret","tagName","element","id","sanitise","str","assignIfUndefined","subject","prop","LogLevel","LOG_PREFIX","convertStringLogLevel","value","level","Logger","component","args","getSiblingsAndPosition","el","originalEl","siblings","position","item","elementPropertiesToCollect","getAllElementProperties","properties","property","parseRawValue","rawValue","parsedValue","getAttributeValue","isJSON","getDomPathProps","attrs","props","attribute","getContextProps","isOriginalEl","customProps","name","getTrace","rootEl","trace","customContext","domPathProps","contextProps","eventPropertiesToCollect","Tracking","subtype","teamName","shadowRoot","category","elements","logger","eventProperties","e","eventData","clickEvent","clickElement","context","triggerAction","extraDetail","_a","ComponentPath","path","org","repo","versionRange","isValidComponentPathObject","p","v","CCCError","message","detail","CCCImportError","CCCRenderError","CCCTimeoutError","_CCCEvent","opts","CCCEvent","_CCCConnectedEvent","CCCConnectedEvent","_CCCReadyEvent","CCCReadyEvent","_CCCViewportEvent","CCCViewportEvent","kebabize","$","ofs","isSafeTestEnv","host","isAllowed","isLocalEnv","isSparkEnv","allowlist","hostname","assignTestURL","testEnv","testUrl","defaultTestUrl","useComponentTestEnv","componentName","FTCustomCodeComponent","entries","entry","componentVersionRange","_b","preambleScript","viteClientScript","supportsDeclarative","internals","error","wrappedError","renderError","app","prerendered","ssr","shadow","styles","template","data","extraProps","onmessage","ready","err","signal","timeout","isTestEnv","resolve","reject","to","componentRenderFunction","oldValue","newValue"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"custom-element.js","sources":["../node_modules/ftdomdelegate/main.js","../../node_modules/@financial-times/o-tracking/src/javascript/utils.js","../src/logger.ts","../src/get-trace.ts","../src/tracking.ts","../src/path.ts","../src/errors.ts","../src/events.ts","../src/util.ts","../src/environment.ts","../src/custom-code-component.ts"],"sourcesContent":["/**\n * DOM event delegator\n *\n * The delegator will listen\n * for events that bubble up\n * to the root node.\n *\n * @constructor\n * @param {Node|string} [root] The root node or a selector string matching the root node\n */\nfunction Delegate(root) {\n\n\t/**\n\t * Maintain a map of listener\n\t * lists, keyed by event name.\n\t *\n\t * @type Object\n\t */\n\tthis.listenerMap = [{}, {}];\n\tif (root) {\n\t\tthis.root(root);\n\t}\n\n\t/** @type function() */\n\tthis.handle = Delegate.prototype.handle.bind(this);\n\n\t// Cache of event listeners removed during an event cycle\n\tthis._removedListeners = [];\n}\n\n/**\n * Start listening for events\n * on the provided DOM element\n *\n * @param {Node|string} [root] The root node or a selector string matching the root node\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.root = function (root) {\n\tconst listenerMap = this.listenerMap;\n\tlet eventType;\n\n\t// Remove master event listeners\n\tif (this.rootElement) {\n\t\tfor (eventType in listenerMap[1]) {\n\t\t\tif (listenerMap[1].hasOwnProperty(eventType)) {\n\t\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, true);\n\t\t\t}\n\t\t}\n\t\tfor (eventType in listenerMap[0]) {\n\t\t\tif (listenerMap[0].hasOwnProperty(eventType)) {\n\t\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, false);\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no root or root is not\n\t// a dom node, then remove internal\n\t// root reference and exit here\n\tif (!root || !root.addEventListener) {\n\t\tif (this.rootElement) {\n\t\t\tdelete this.rootElement;\n\t\t}\n\t\treturn this;\n\t}\n\n\t/**\n\t * The root node at which\n\t * listeners are attached.\n\t *\n\t * @type Node\n\t */\n\tthis.rootElement = root;\n\n\t// Set up master event listeners\n\tfor (eventType in listenerMap[1]) {\n\t\tif (listenerMap[1].hasOwnProperty(eventType)) {\n\t\t\tthis.rootElement.addEventListener(eventType, this.handle, true);\n\t\t}\n\t}\n\tfor (eventType in listenerMap[0]) {\n\t\tif (listenerMap[0].hasOwnProperty(eventType)) {\n\t\t\tthis.rootElement.addEventListener(eventType, this.handle, false);\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * @param {string} eventType\n * @returns boolean\n */\nDelegate.prototype.captureForType = function (eventType) {\n\treturn ['blur', 'error', 'focus', 'load', 'resize', 'scroll'].indexOf(eventType) !== -1;\n};\n\n/**\n * Attach a handler to one\n * event for all elements\n * that match the selector,\n * now or in the future\n *\n * The handler function receives\n * three arguments: the DOM event\n * object, the node that matched\n * the selector while the event\n * was bubbling and a reference\n * to itself. Within the handler,\n * 'this' is equal to the second\n * argument.\n *\n * The node that actually received\n * the event can be accessed via\n * 'event.target'.\n *\n * @param {string} eventType Listen for these events\n * @param {string|undefined} selector Only handle events on elements matching this selector, if undefined match root element\n * @param {function()} handler Handler function - event data passed here will be in event.data\n * @param {boolean} [useCapture] see 'useCapture' in <https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener>\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.on = function (eventType, selector, handler, useCapture) {\n\tlet root;\n\tlet listenerMap;\n\tlet matcher;\n\tlet matcherParam;\n\n\tif (!eventType) {\n\t\tthrow new TypeError('Invalid event type: ' + eventType);\n\t}\n\n\t// handler can be passed as\n\t// the second or third argument\n\tif (typeof selector === 'function') {\n\t\tuseCapture = handler;\n\t\thandler = selector;\n\t\tselector = null;\n\t}\n\n\t// Fallback to sensible defaults\n\t// if useCapture not set\n\tif (useCapture === undefined) {\n\t\tuseCapture = this.captureForType(eventType);\n\t}\n\n\tif (typeof handler !== 'function') {\n\t\tthrow new TypeError('Handler must be a type of Function');\n\t}\n\n\troot = this.rootElement;\n\tlistenerMap = this.listenerMap[useCapture ? 1 : 0];\n\n\t// Add master handler for type if not created yet\n\tif (!listenerMap[eventType]) {\n\t\tif (root) {\n\t\t\troot.addEventListener(eventType, this.handle, useCapture);\n\t\t}\n\t\tlistenerMap[eventType] = [];\n\t}\n\n\tif (!selector) {\n\t\tmatcherParam = null;\n\n\t\t// COMPLEX - matchesRoot needs to have access to\n\t\t// this.rootElement, so bind the function to this.\n\t\tmatcher = matchesRoot.bind(this);\n\n\t\t// Compile a matcher for the given selector\n\t} else if (/^[a-z]+$/i.test(selector)) {\n\t\tmatcherParam = selector;\n\t\tmatcher = matchesTag;\n\t} else if (/^#[a-z0-9\\-_]+$/i.test(selector)) {\n\t\tmatcherParam = selector.slice(1);\n\t\tmatcher = matchesId;\n\t} else {\n\t\tmatcherParam = selector;\n\t\tmatcher = Element.prototype.matches;\n\t}\n\n\t// Add to the list of listeners\n\tlistenerMap[eventType].push({\n\t\tselector: selector,\n\t\thandler: handler,\n\t\tmatcher: matcher,\n\t\tmatcherParam: matcherParam\n\t});\n\n\treturn this;\n};\n\n/**\n * Remove an event handler\n * for elements that match\n * the selector, forever\n *\n * @param {string} [eventType] Remove handlers for events matching this type, considering the other parameters\n * @param {string} [selector] If this parameter is omitted, only handlers which match the other two will be removed\n * @param {function()} [handler] If this parameter is omitted, only handlers which match the previous two will be removed\n * @returns {Delegate} This method is chainable\n */\nDelegate.prototype.off = function (eventType, selector, handler, useCapture) {\n\tlet i;\n\tlet listener;\n\tlet listenerMap;\n\tlet listenerList;\n\tlet singleEventType;\n\n\t// Handler can be passed as\n\t// the second or third argument\n\tif (typeof selector === 'function') {\n\t\tuseCapture = handler;\n\t\thandler = selector;\n\t\tselector = null;\n\t}\n\n\t// If useCapture not set, remove\n\t// all event listeners\n\tif (useCapture === undefined) {\n\t\tthis.off(eventType, selector, handler, true);\n\t\tthis.off(eventType, selector, handler, false);\n\t\treturn this;\n\t}\n\n\tlistenerMap = this.listenerMap[useCapture ? 1 : 0];\n\tif (!eventType) {\n\t\tfor (singleEventType in listenerMap) {\n\t\t\tif (listenerMap.hasOwnProperty(singleEventType)) {\n\t\t\t\tthis.off(singleEventType, selector, handler);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n\n\tlistenerList = listenerMap[eventType];\n\tif (!listenerList || !listenerList.length) {\n\t\treturn this;\n\t}\n\n\t// Remove only parameter matches\n\t// if specified\n\tfor (i = listenerList.length - 1; i >= 0; i--) {\n\t\tlistener = listenerList[i];\n\n\t\tif ((!selector || selector === listener.selector) && (!handler || handler === listener.handler)) {\n\t\t\tthis._removedListeners.push(listener);\n\t\t\tlistenerList.splice(i, 1);\n\t\t}\n\t}\n\n\t// All listeners removed\n\tif (!listenerList.length) {\n\t\tdelete listenerMap[eventType];\n\n\t\t// Remove the main handler\n\t\tif (this.rootElement) {\n\t\t\tthis.rootElement.removeEventListener(eventType, this.handle, useCapture);\n\t\t}\n\t}\n\n\treturn this;\n};\n\n\n/**\n * Handle an arbitrary event.\n *\n * @param {Event} event\n */\nDelegate.prototype.handle = function (event) {\n\tlet i;\n\tlet l;\n\tconst type = event.type;\n\tlet root;\n\tlet phase;\n\tlet listener;\n\tlet returned;\n\tlet listenerList = [];\n\tlet target;\n\tconst eventIgnore = 'ftLabsDelegateIgnore';\n\n\tif (event[eventIgnore] === true) {\n\t\treturn;\n\t}\n\n\ttarget = event.target;\n\n\t// Hardcode value of Node.TEXT_NODE\n\t// as not defined in IE8\n\tif (target.nodeType === 3) {\n\t\ttarget = target.parentNode;\n\t}\n\n\t// Handle SVG <use> elements in IE\n\tif (target.correspondingUseElement) {\n\t\ttarget = target.correspondingUseElement;\n\t}\n\n\troot = this.rootElement;\n\n\tphase = event.eventPhase || (event.target !== event.currentTarget ? 3 : 2);\n\n\t// eslint-disable-next-line default-case\n\tswitch (phase) {\n\t\tcase 1: //Event.CAPTURING_PHASE:\n\t\t\tlistenerList = this.listenerMap[1][type];\n\t\t\tbreak;\n\t\tcase 2: //Event.AT_TARGET:\n\t\t\tif (this.listenerMap[0] && this.listenerMap[0][type]) {\n\t\t\t\tlistenerList = listenerList.concat(this.listenerMap[0][type]);\n\t\t\t}\n\t\t\tif (this.listenerMap[1] && this.listenerMap[1][type]) {\n\t\t\t\tlistenerList = listenerList.concat(this.listenerMap[1][type]);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 3: //Event.BUBBLING_PHASE:\n\t\t\tlistenerList = this.listenerMap[0][type];\n\t\t\tbreak;\n\t}\n\n\tlet toFire = [];\n\n\t// Need to continuously check\n\t// that the specific list is\n\t// still populated in case one\n\t// of the callbacks actually\n\t// causes the list to be destroyed.\n\tl = listenerList.length;\n\twhile (target && l) {\n\t\tfor (i = 0; i < l; i++) {\n\t\t\tlistener = listenerList[i];\n\n\t\t\t// Bail from this loop if\n\t\t\t// the length changed and\n\t\t\t// no more listeners are\n\t\t\t// defined between i and l.\n\t\t\tif (!listener) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ttarget.tagName &&\n\t\t\t\t[\"button\", \"input\", \"select\", \"textarea\"].indexOf(target.tagName.toLowerCase()) > -1 &&\n\t\t\t\ttarget.hasAttribute(\"disabled\")\n\t\t\t) {\n\t\t\t\t// Remove things that have previously fired\n\t\t\t\ttoFire = [];\n\t\t\t}\n\t\t\t// Check for match and fire\n\t\t\t// the event if there's one\n\t\t\t//\n\t\t\t// TODO:MCG:20120117: Need a way\n\t\t\t// to check if event#stopImmediatePropagation\n\t\t\t// was called. If so, break both loops.\n\t\t\telse if (listener.matcher.call(target, listener.matcherParam, target)) {\n\t\t\t\ttoFire.push([event, target, listener]);\n\t\t\t}\n\t\t}\n\n\t\t// TODO:MCG:20120117: Need a way to\n\t\t// check if event#stopPropagation\n\t\t// was called. If so, break looping\n\t\t// through the DOM. Stop if the\n\t\t// delegation root has been reached\n\t\tif (target === root) {\n\t\t\tbreak;\n\t\t}\n\n\t\tl = listenerList.length;\n\n\t\t// Fall back to parentNode since SVG children have no parentElement in IE\n\t\ttarget = target.parentElement || target.parentNode;\n\n\t\t// Do not traverse up to document root when using parentNode, though\n\t\tif (target instanceof HTMLDocument) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet ret;\n\n\tfor (i = 0; i < toFire.length; i++) {\n\t\t// Has it been removed during while the event function was fired\n\t\tif (this._removedListeners.indexOf(toFire[i][2]) > -1) {\n\t\t\tcontinue;\n\t\t}\n\t\treturned = this.fire.apply(this, toFire[i]);\n\n\t\t// Stop propagation to subsequent\n\t\t// callbacks if the callback returned\n\t\t// false\n\t\tif (returned === false) {\n\t\t\ttoFire[i][0][eventIgnore] = true;\n\t\t\ttoFire[i][0].preventDefault();\n\t\t\tret = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n/**\n * Fire a listener on a target.\n *\n * @param {Event} event\n * @param {Node} target\n * @param {Object} listener\n * @returns {boolean}\n */\nDelegate.prototype.fire = function (event, target, listener) {\n\treturn listener.handler.call(target, event, target);\n};\n\n/**\n * Check whether an element\n * matches a tag selector.\n *\n * Tags are NOT case-sensitive,\n * except in XML (and XML-based\n * languages such as XHTML).\n *\n * @param {string} tagName The tag name to test against\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesTag(tagName, element) {\n\treturn tagName.toLowerCase() === element.tagName.toLowerCase();\n}\n\n/**\n * Check whether an element\n * matches the root.\n *\n * @param {?String} selector In this case this is always passed through as null and not used\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesRoot(selector, element) {\n\tif (this.rootElement === window) {\n\t\treturn (\n\t\t\t// Match the outer document (dispatched from document)\n\t\t\telement === document ||\n\t\t\t// The <html> element (dispatched from document.body or document.documentElement)\n\t\t\telement === document.documentElement ||\n\t\t\t// Or the window itself (dispatched from window)\n\t\t\telement === window\n\t\t);\n\t}\n\treturn this.rootElement === element;\n}\n\n/**\n * Check whether the ID of\n * the element in 'this'\n * matches the given ID.\n *\n * IDs are case-sensitive.\n *\n * @param {string} id The ID to test against\n * @param {Element} element The element to test with\n * @returns boolean\n */\nfunction matchesId(id, element) {\n\treturn id === element.id;\n}\n\n/**\n * Short hand for off()\n * and root(), ie both\n * with no parameters\n *\n * @return void\n */\nDelegate.prototype.destroy = function () {\n\tthis.off();\n\tthis.root();\n};\n\nexport default Delegate;\n","/**\n * Shared 'internal' scope.\n */\nimport {get} from './core/settings.js';\n\n/**\n * CUID Generator\n */\nimport {api as cuid} from '../libs/browser-cuid.js';\n\n/**\n * Record of callbacks to call when a page is tracked.\n */\nconst page_callbacks = [];\n\n/**\n * Log messages to the browser console. Requires 'log' to be set on init.\n *\n * @param {*} args items to log\n * @returns {void}\n */\nfunction log(...args) {\n\tif (get('config').test && window.console) {\n\t\tfor (const arg of args) {\n\t\t\twindow.console.log(arg);\n\t\t}\n\t}\n}\n\n/**\n * Creates a logging function that logs messages to the console with a specified namespace.\n *\n * @function namedLog\n * @param {string} namespace - The namespace to be prefixed to each log message.\n * @returns {function} A function that logs messages to the console with the given namespace if the configuration allows.\n *\n * @example\n * const log = namedLog('MyNamespace');\n * log('This is a message'); \n * // Output: [MyNamespace]: This is a message\n */\nfunction namedLog(namespace) {\n\treturn function(...args) {\n\t\tif(get('config').test && window.console) {\n\t\t\twindow.console.log(`%c[${namespace}]:`, 'color: teal', ...args)\n\t\t}\n\t}\n}\n\n/**\n * Tests if variable is a certain type. Defaults to check for undefined if no type specified.\n *\n * @param {*} variable - The variable to check.\n * @param {string=} type - The type to test for. Defaults to undefined.\n *\n * @returns {boolean} - The answer for if the variable is of type.\n */\nfunction is(variable, type = 'undefined') {\n\treturn typeof variable === type;\n}\n\n/**\n * Merge objects together. Will remove undefined and null values.\n *\n * @param {object} target - The original object to merge in to.\n * @param {object} options - The object to merge into the target. If omitted, will merge target into a new empty Object.\n *\n * @returns {object} The merged object.\n */\nfunction merge(target, options) {\n\tif (!options) {\n\t\toptions = target;\n\t\ttarget = {};\n\t}\n\n\tlet name;\n\tlet src;\n\tlet copy;\n\n\t/* jshint -W089 */\n\t/* eslint guard-for-in: 0 */\n\tfor (name in options) {\n\t\tsrc = target[name];\n\t\tcopy = options[name];\n\n\t\t// Prevent never-ending loop\n\t\tif (target === copy) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Gets rid of missing values too\n\t\tif (typeof copy !== 'undefined' && copy !== null) {\n\t\t\ttarget[name] = src === Object(src) && !is(src, 'function') ? merge(src, copy) : copy;\n\t\t}\n\t}\n\t/* jshint +W089 */\n\t/* jslint forin:true */\n\n\treturn target;\n}\n\n/**\n * URL encode a string.\n *\n * @param {string} str - The string to be encoded.\n * @returns {string} The encoded string.\n */\nfunction encode(str) {\n\tif (window.encodeURIComponent) {\n\t\treturn window.encodeURIComponent(str);\n\t} else {\n\t\treturn window.escape(str);\n\t}\n}\n\n/**\n * URL decode a string.\n *\n * @param {string} str - The string to be decoded.\n * @returns {string} The decoded string.\n */\nfunction decode(str) {\n\tif (window.decodeURIComponent) {\n\t\treturn window.decodeURIComponent(str);\n\t} else {\n\t\treturn window.unescape(str);\n\t}\n}\n\n/**\n * Utility to add event listeners.\n *\n * @param {Element} element\n * @param {string} event\n * @param {EventListenerOrEventListenerObject} listener\n * @returns {void}\n */\nfunction addEvent(element, event, listener) {\n\tif (element.addEventListener) {\n\t\telement.addEventListener(event, listener, false);\n\t} else {\n\t\telement.attachEvent('on' + event, listener);\n\t}\n}\n\n/**\n * Utility for dispatching custom events from window\n *\n * @param {string} namespace\n * @param {string} eventType\n * @param {object} detail\n * @returns {void}\n */\nfunction broadcast(namespace, eventType, detail) {\n\tdetail = detail || {};\n\ttry {\n\t\twindow.dispatchEvent(new CustomEvent(namespace + '.' + eventType, {\n\t\t\tdetail: detail,\n\t\t\tbubbles: true\n\t\t}));\n\t} catch (error) {\n\t\t// empty\n\t}\n}\n\n/**\n * Listen for page tracking requests.\n *\n * @param {Function} cb - The callback to be called whenever a page is tracked.\n * @returns {void}\n */\nfunction onPage(cb) {\n\tif (is(cb, 'function') && !page_callbacks.includes(cb)) {\n\t\tpage_callbacks.push(cb);\n\t}\n}\n\n/**\n * Trigger the 'page' listeners.\n *\n * @returns {void}\n */\nfunction triggerPage() {\n\tfor (let i = 0; i < page_callbacks.length; i++) {\n\t\tpage_callbacks[i]();\n\t}\n}\n\n/**\n * Get a value from document.cookie matching the first match of the regexp you supply\n *\n * @param {RegExp} matcher - The Regex to match with\n * @returns {string} - The vale from the cookie\n */\nfunction getValueFromCookie(matcher) {\n\treturn document.cookie.match(matcher) && RegExp.$1 !== '' && RegExp.$1 !== 'null' ? RegExp.$1 : null;\n}\n\n/**\n * Filter an object to only have the properties which are listed in the `allowlist` parameter.\n *\n * @param {object} objectToFilter - An object whose props need to be filtered\n * @param {Array} allowedPropertyNames - The list of props to allow\n * @returns {object} An object containing only the allowed props\n */\nfunction filterProperties (objectToFilter, allowedPropertyNames) {\n\tconst filteredObject = {};\n\tfor (const allowedName of allowedPropertyNames) {\n\t\tif (objectToFilter[allowedName]) {\n\t\t\tfilteredObject[allowedName] = objectToFilter[allowedName];\n\t\t}\n\t}\n\treturn filteredObject;\n}\n\n/**\n * Trim strings\n *\n * @param {string} str - The string to trim.\n * @returns {string} The trimmed string.\n */\nfunction sanitise (str) {\n\treturn typeof str === 'string' ? str.trim() : str;\n}\n\n/**\n * Assign the subject value if the target properties are undefined\n *\n * @param {object} subject - assign the value\n * @param {object} target - be assigned the value\n * @returns {void}\n */\nfunction assignIfUndefined (subject, target) {\n\tfor (const prop in subject) {\n\t\tif (!target[prop]) {\n\t\t\ttarget[prop] = subject[prop];\n\t\t} else {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`You can't set a custom property called ${prop}`);\n\t\t}\n\t}\n}\n\n\n/**\n * Identify circular references in 'object', and replace them with a string representation\n * of the reference. Returns a succesfully serialised JSON string, and a list of circular\n * references which were removed.\n * \n * Inspired by https://github.com/sindresorhus/safe-stringify and \n * https://github.com/sindresorhus/decircular\n *\n * @param {*} object The object we want to stringify, and search within for circular references\n * @returns {Object: {jsonString: string, warnings: array}} The stringified object, and a warnings for each circular reference which was removed\n */\nfunction removeCircularReferences(object) {\n\n\t// WeakMaps release memory when all references are garbage-collected\n\tconst circularReferences = new WeakMap();\n\tconst paths = new WeakMap();\n\n\tconst warnings = [];\n\n\tfunction getPathFragment(parent, key) {\n\t\tif (!key) {\n\t\t\treturn '$';\n\t\t}\n\n\t\tif (Array.isArray(parent)) {\n\t\t\treturn `[${key}]`;\n\t\t}\n\n\t\treturn `.${key}`;\n\t}\n\n\tfunction formatCircularReferencesWarning(references) {\n\t\tconst paths = references.map(path => '`' + path.join('') + '`');\n\t\treturn 'Circular reference between ' + paths.join(' AND ');\n\t}\n\n\tfunction replacer(key, value) {\n\t\t// Scalars don't need to be inspected as they can't contain circular references\n\t\tif (!(value !== null && typeof value === 'object')) {\n\t\t\treturn value\n\t\t}\n\n\t\t// Record the path from the root ($) to the current object (value)\n\t\t// in order to print helpful circular reference warnings.\n\t\tconst path = [...paths.get(this) || [], getPathFragment(this, key)];\n\t\tpaths.set(value, path);\n\n\t\t// If a reference to the current value is already in the list, we have\n\t\t// a circular reference. Add the current value to the list along with its path,\n\t\t// and return a useful error string rather than the unserialisable value.\n\t\tif (circularReferences.has(value)) {\n\t\t\tconst references = [...circularReferences.get(value), path];\n\t\t\tcircularReferences.set(value, references);\n\t\t\tconst warning = formatCircularReferencesWarning(references);\n\t\t\twarnings.push(warning);\n\t\t\treturn warning;\n\t\t}\n\n\t\t// This is the first time we've seen the current value in this branch \n\t\t// of the object. Record its path from the object root.\n\t\tcircularReferences.set(value, [path]);\n\n\t\t// Recurse into the value to proactively find circular references\n\t\t// before encountering a loop.\n\t\tconst newValue = Array.isArray(value) ? [] : {};\n\t\tfor (const [k, v] of Object.entries(value)) {\n\t\t\tnewValue[k] = replacer.call(value, k, v);\n\t\t}\n\n\t\t// All circular references to this object will have been identified,\n\t\t// so remove it from the list.\n\t\tcircularReferences.delete(value);\n\n\t\t// This branch of the object can now be safely serialised to a JSON string\n\t\treturn newValue;\n\t}\n\n\tconst jsonString = JSON.stringify(object, replacer);\n\treturn {jsonString, warnings};\n}\n\n\n/**\n * Stringify an object to JSON, removing any circular references. When circular references\n * are found, an error is thrown in a new event loop so that global error handlers can report it.\n *\n * @param {*} object The object we want to stringify, and search within for circular references\n * @returns {string} The safely stringified JSON string\n */\nfunction safelyStringifyJson(object) {\n\n\t// JSON.stringify throws on two cases:\n\t// - value contains a circular reference\n\t// - A BigInt value is encountered\n\t// Circular references are a real possibility in the way o-tracking is called (and saves a queue of \n\t// messages in a store), so we need to handle those gracefully.\n\t// \n\t// However, for performance reasons, we always attempt to do a basic JSON.stringify() first. The \n\t// recursion involved in removeCircularReferences() makes it about 20x slower to stringify a basic payload. \n\t// This performance hit will be exacerbated on slow devices (e.g. old Android phones) with lots of queued offline events.\n\ttry {\n\t\treturn JSON.stringify(object);\n\n\t// NB: error is discarded - we have more work to do in order to throw a useful message\n\t} catch (error) {\n\t\n\t\tconst {jsonString, warnings} = removeCircularReferences(object);\n\t\n\t\tif (warnings.length) {\n\t\t\t// Throw in a new event loop, as we always want to return JSON so the tracking payload is sent\n\t\t\tsetTimeout(() => {\n\t\t\t\tconst errorMessage = \"AssertionError: o-tracking does not support circular references in the analytics data.\\n\" +\n\t\t\t\t\"Please remove the circular references in the data.\\n\" +\n\t\t\t\t\"Here are the paths in the data which are circular:\\n\" +\n\t\t\t\twarnings.join('\\n');\n\t\t\t\tthrow new Error(errorMessage);\n\t\t\t});\n\t\t}\n\t\n\t\treturn jsonString;\n\t}\n\n\n};\n\n/**\n * Find out whether two objects are deeply equal to each other.\n *\n * @param {*} a\n * @param {*} b\n * @returns {boolean} - true if the two arguments are deeply equal\n */\nfunction isDeepEqual(a, b) {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (\n\t\ta &&\n\t\tb &&\n\t\ttypeof a === \"object\" &&\n\t\ttypeof b === \"object\"\n\t) {\n\t\tif (a.constructor !== b.constructor) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (Array.isArray(a)) {\n\t\t\tconst length = a.length;\n\t\t\tif (length !== b.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\t\tif (!isDeepEqual(a[i], b[i])) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tif (a.constructor === RegExp) {\n\t\t\treturn (\n\t\t\t\ta.source === b.source && a.flags === b.flags\n\t\t\t);\n\t\t}\n\t\tif (a.valueOf !== Object.prototype.valueOf) {\n\t\t\treturn a.valueOf() === b.valueOf();\n\t\t}\n\t\tif (a.toString !== Object.prototype.toString) {\n\t\t\treturn a.toString() === b.toString();\n\t\t}\n\n\t\tconst keys = Object.keys(a);\n\t\tconst length = keys.length;\n\t\tif (length !== Object.keys(b).length) {\n\t\t\treturn false;\n\t\t}\n\n\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(b, keys[i])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tfor (let i = length; i-- !== 0; ) {\n\t\t\tconst key = keys[i];\n\n\t\t\tif (!isDeepEqual(a[key], b[key])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n}\n\nexport {\n\tlog,\n\tnamedLog,\n\tis,\n\tis as isUndefined,\n\tmerge,\n\tencode,\n\tdecode,\n\tcuid as guid,\n\taddEvent,\n\tbroadcast,\n\tonPage,\n\ttriggerPage,\n\tgetValueFromCookie,\n\tsanitise,\n\tassignIfUndefined,\n\tfilterProperties,\n\tremoveCircularReferences,\n\tsafelyStringifyJson,\n\tisDeepEqual\n};\n","import { ComponentPath } from \"./path\";\n\nexport const LogLevel = Object.freeze({\n DEBUG: 0,\n INFO: 1,\n WARN: 2,\n ERROR: 3,\n TEST: 4,\n DEFAULT: 2,\n});\n\nconst LOG_PREFIX = \"CCC:\";\n\nexport function convertStringLogLevel(value: string | null) {\n const level = value?.toLowerCase();\n\n if (level === \"debug\") {\n return LogLevel.DEBUG;\n }\n\n if (level === \"info\") {\n return LogLevel.INFO;\n }\n\n if (level === \"warn\") {\n return LogLevel.WARN;\n }\n\n if (level === \"error\") {\n return LogLevel.ERROR;\n }\n\n if (level === \"test\") {\n return LogLevel.TEST;\n }\n\n return LogLevel.DEFAULT;\n}\n\nexport class Logger {\n public level: number;\n public component?: ComponentPath;\n\n constructor(\n {\n level = LogLevel.DEFAULT,\n component,\n }: { level: number; component?: ComponentPath } = {\n level: LogLevel.DEFAULT,\n }\n ) {\n this.level = localStorage?.getItem(\"CCC_LOG_LEVEL\")\n ? convertStringLogLevel(localStorage.getItem(\"CCC_LOG_LEVEL\"))\n : level;\n this.component = component;\n }\n\n private formatConsoleArgs(args: any[]) {\n const suffix = this.component ? [this.component] : [];\n\n if (args.length === 0) {\n return [LOG_PREFIX, ...suffix];\n }\n\n const [first, ...rest] = args;\n\n if (typeof first === \"string\") {\n return [`${LOG_PREFIX} ${first}`, ...rest, ...suffix];\n }\n\n return [LOG_PREFIX, first, ...rest, ...suffix];\n }\n\n debug(...args: any[]) {\n if (this.level <= LogLevel.DEBUG) {\n console.info(...this.formatConsoleArgs(args));\n }\n }\n\n log = this.debug;\n\n info(...args: any[]) {\n if (this.level <= LogLevel.INFO) {\n console.info(...this.formatConsoleArgs(args));\n }\n }\n\n warn(...args: any[]) {\n if (this.level <= LogLevel.WARN) {\n console.warn(...this.formatConsoleArgs(args));\n }\n }\n\n error(...args: any[]) {\n if (this.level <= LogLevel.ERROR) {\n console.error(...this.formatConsoleArgs(args));\n }\n }\n\n setLogLevel(level: string | number | null) {\n if (localStorage?.getItem(\"CCC_LOG_LEVEL\")) {\n this.level = convertStringLogLevel(localStorage.getItem(\"CCC_LOG_LEVEL\"));\n } else if (typeof level === \"number\") {\n this.level = level;\n } else {\n this.level = convertStringLogLevel(level);\n }\n }\n}\n","// Trace the element and all of its parents, collecting properties as we go\nimport {\n sanitise,\n assignIfUndefined,\n} from \"@financial-times/o-tracking/src/javascript/utils\";\n\ntype PropMap = { [k: string]: any };\n// For a given container element, get the number of elements that match the\n// original element (siblings); and the index of the original element (position).\nconst getSiblingsAndPosition = (\n el: Element | null,\n originalEl: Element,\n selector: string\n) => {\n const siblings = Array.from(el?.querySelectorAll(selector) ?? []);\n const position = siblings.findIndex((item) => item === originalEl);\n if (position === -1) {\n return;\n }\n return {\n siblings: siblings.length,\n position,\n };\n};\n\nconst elementPropertiesToCollect = [\n \"nodeName\",\n \"className\",\n \"id\",\n \"href\",\n \"text\",\n \"role\",\n];\n// Get all (sanitised) properties of a given element.\nconst getAllElementProperties = (element: any) => {\n const properties: PropMap = {};\n for (const property of elementPropertiesToCollect) {\n const value =\n element[property] ||\n element.getAttribute(property) ||\n element.hasAttribute(property);\n if (value !== undefined) {\n if (typeof value === \"boolean\") {\n properties[property] = value;\n } else {\n properties[property] = sanitise(value);\n }\n }\n }\n\n return properties;\n};\n\nconst parseRawValue = (rawValue: string) => {\n try {\n const parsedValue = JSON.parse(rawValue);\n const type = Object.prototype.toString.call(parsedValue);\n const isJSON = type === \"[object Object]\" || type === \"[object Array]\";\n\n return [isJSON, parsedValue];\n } catch (error) {\n return [false, null];\n }\n};\n\nconst getAttributeValue = (rawValue: string) => {\n const [isJSON, value] = parseRawValue(rawValue);\n\n return isJSON ? value : rawValue;\n};\n\n// Get some properties of a given element.\nconst getDomPathProps = (attrs: Attr[], props: PropMap) => {\n // Collect any attribute that matches given strings.\n attrs\n .filter((attribute) =>\n attribute.name.match(/^data-trackable|^data-o-|^aria-/i)\n )\n .forEach((attribute) => {\n props[attribute.name] = attribute.value;\n });\n\n return props;\n};\n\n// Get only the custom data-trackable-context-? properties of a given element\nconst getContextProps = (\n attrs: Attr[],\n props: PropMap,\n isOriginalEl: boolean\n) => {\n const customProps: { [k: string]: any } = {};\n\n // for the original element collect properties like className, nodeName\n if (isOriginalEl) {\n elementPropertiesToCollect.forEach((name) => {\n if (typeof props[name] !== \"undefined\" && name !== \"id\") {\n customProps[name] = props[name];\n }\n });\n }\n\n // Collect any attribute that matches given strings.\n attrs\n .filter((attribute) => attribute.name.match(/^data-trackable-context-/i))\n .forEach((attribute) => {\n customProps[attribute.name.replace(\"data-trackable-context-\", \"\")] =\n getAttributeValue(attribute.value);\n });\n\n return customProps;\n};\n\nexport function getTrace(el: Element, rootEl: Element) {\n const originalEl = el;\n const selector = originalEl?.getAttribute(\"data-trackable\")\n ? `[data-trackable=\"${originalEl.getAttribute(\"data-trackable\")}\"]`\n : originalEl?.nodeName;\n const trace = [];\n const customContext = {};\n while (el && el !== rootEl) {\n const props = getAllElementProperties(el);\n const attrs = Array.from(el.attributes);\n let domPathProps = getDomPathProps(attrs, props);\n\n // If the element happens to have a data-trackable attribute, get the siblings\n // and position of the element (relative to the current element).\n if (domPathProps[\"data-trackable\"]) {\n domPathProps = Object.assign(\n domPathProps,\n getSiblingsAndPosition(el, originalEl, selector)\n );\n }\n\n trace.push(domPathProps);\n\n const contextProps = getContextProps(attrs, props, el === originalEl);\n\n assignIfUndefined(contextProps, customContext);\n\n el = el.parentNode as Element;\n }\n return { trace, customContext };\n}\n","import Delegate from \"ftdomdelegate/main\";\n\nimport {\n sanitise,\n assignIfUndefined,\n} from \"@financial-times/o-tracking/src/javascript/utils\";\nimport { Logger } from \"./logger\";\nimport { getTrace } from \"./get-trace\";\n\nconst eventPropertiesToCollect = [\"ctrlKey\", \"altKey\", \"shiftKey\", \"metaKey\"];\n\nclass Tracking {\n cccId: string;\n cccName: string;\n subtype: string;\n teamName: string;\n shadowRoot: ShadowRoot | null;\n category: string;\n elements: string | string[];\n isInitialised: boolean;\n log: Logger;\n shadowDelegate: typeof Delegate;\n\n constructor({\n id = \"00000000-0000-0000-0000-000000000000\",\n name = \"ccc-component\",\n subtype = \"interactive\",\n teamName = \"djd\",\n shadowRoot = null,\n category = \"cta\",\n elements = 'a, button, input, [role=\"button\"]',\n logger,\n }: {\n id?: string;\n name: string;\n subtype: string;\n teamName?: string;\n shadowRoot: ShadowRoot | null;\n category?: string;\n elements?: string | string[];\n logger: Logger;\n }) {\n this.cccId = id;\n this.cccName = name;\n this.subtype = subtype;\n this.teamName = teamName;\n this.shadowRoot = shadowRoot;\n this.category = category;\n this.elements = elements;\n this.isInitialised = false;\n this.log = logger ?? new Logger();\n }\n\n // Get properties for the event (as opposed to properties of the clicked element)\n getEventProperties(event: any) {\n const eventProperties: { [k: string]: any } = {};\n for (const property of eventPropertiesToCollect) {\n if (event[property]) {\n try {\n eventProperties[property] = sanitise(event[property]);\n } catch (e) {\n this.log.info(e);\n }\n }\n }\n return eventProperties;\n }\n\n // Controller for handling click events\n handleClickEvent(\n eventData: { action: string; category: string },\n root: Element,\n ) {\n return (clickEvent: Event, clickElement: HTMLElement) => {\n const context: any = this.getEventProperties(clickEvent);\n const { trace, customContext } = getTrace(clickElement, root);\n context.custom =\n clickElement.dataset && clickElement.dataset.custom\n ? JSON.parse(clickElement.dataset.custom)\n : null;\n context.domPathTokens = trace;\n context.component = {\n id: this.cccId,\n name: this.cccName,\n type: \"custom-code-component\",\n subtype: this.subtype,\n };\n context.teamName = this.teamName;\n context.url = document.URL;\n\n assignIfUndefined(customContext, context);\n\n context.method = \"ftCustomAnalytics\";\n eventData = { ...eventData, ...context };\n\n // send spoor event\n document.body.dispatchEvent(\n new CustomEvent(\"oTracking.event\", {\n detail: eventData,\n bubbles: true,\n composed: true,\n }),\n );\n };\n }\n\n sendSpoorEvent(triggerAction: any, extraDetail: any) {\n const eventData = {\n category: \"component\",\n action: \"act\",\n component: {\n id: this.cccId,\n name: this.cccName,\n type: \"custom-code-component\",\n subtype: this.subtype,\n },\n teamName: this.teamName,\n trigger_action: triggerAction,\n custom: extraDetail,\n method: \"ftCustomAnalytics\",\n };\n\n // send spoor event\n document.body.dispatchEvent(\n new CustomEvent(\"oTracking.event\", {\n detail: eventData,\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n init(id: string) {\n if (!this.isInitialised) {\n this.isInitialised = true;\n this.cccId = id ? id : this.cccId;\n\n const eventData = {\n action: \"click\",\n category: this.category,\n };\n\n const root = this.shadowRoot?.querySelector(\"[data-component-root]\");\n\n if (root) {\n this.shadowDelegate = new Delegate(root);\n this.shadowDelegate.on(\n \"click\",\n this.elements,\n this.handleClickEvent(eventData, root),\n true,\n );\n }\n }\n }\n\n destroy() {\n this.shadowDelegate?.off();\n }\n}\n\nexport default Tracking;\n","import { CCCError } from \"./errors\";\n\nexport type ComponentPathType = {\n org: string;\n repo: string;\n name: string;\n versionRange: string;\n};\nexport class ComponentPath {\n org: string = \"local\";\n repo: string = \"dev\";\n name: string;\n versionRange: string;\n\n constructor(path?: ComponentPathType | string) {\n const { org, repo, name, versionRange } = isValidComponentPathObject(path)\n ? path\n : ComponentPath.fromString(path);\n if (org) this.org = org;\n if (repo) this.repo = repo;\n this.name = name;\n this.versionRange = versionRange;\n }\n\n set path(path: ComponentPathType | string) {\n const { org, repo, name, versionRange } = isValidComponentPathObject(path)\n ? path\n : ComponentPath.fromString(path);\n this.org = org;\n this.repo = repo;\n this.name = name;\n this.versionRange = versionRange;\n }\n\n get path(): string {\n return `${this.org}/${this.repo}@${this.versionRange}/${this.name}`;\n }\n\n get isValid(): boolean {\n return [this.org, this.repo, this.name].every(\n (value) => value !== \"unknown\"\n );\n }\n\n toString(): string {\n return this.path;\n }\n\n static fromString(p?: string | null, v?: string | null): ComponentPath {\n const path = p ?? \"unknown/unknown/unknown\";\n\n const [name, repo, org] = path\n .replace(/@[^\\/]+/, \"\")\n .split(\"/\")\n .reverse();\n\n const versionRange =\n v ??\n path\n .match(/@[^\\/]+/)\n ?.toString()\n .replace(\"@\", \"\") ??\n \"unknown\";\n\n if (repo && !versionRange) throw new CCCError(\"No version specified\");\n\n return new ComponentPath({ org, repo, name, versionRange });\n }\n}\n\nexport type DetailType = {\n component: ComponentPath;\n source?: string;\n cause?: string;\n error?: Error;\n};\n\nexport function isValidComponentPathObject(\n value: unknown\n): value is ComponentPathType {\n if (typeof value === \"object\" && value !== null) {\n return \"org\" in value && \"repo\" in value && \"name\" in value;\n }\n\n return false;\n}\n","/**\n * This is the base CCC component error class. These are raised when the component being loaded errors\n */\n\nimport { ComponentPath, DetailType, isValidComponentPathObject } from \"./path\";\n\nexport class CCCError extends Error {\n component: ComponentPath | null;\n source?: string;\n errors?: Error[];\n constructor(message: string | null, detail?: DetailType) {\n if (!detail && message) {\n super(message);\n this.component = null;\n } else if (typeof detail?.component === \"string\") {\n super(\n message ??\n `${detail.cause ?? \"Unknown error\"} in ${detail.component} imported from ${detail.source ?? \"an undefined source\"}.`\n );\n\n this.component = ComponentPath.fromString(detail.component);\n } else if (isValidComponentPathObject(detail?.component)) {\n super(\n message ??\n `${detail.cause ?? \"Unknown error\"} in ${detail.component.org}/${detail.component.repo}/${detail.component.name}@${detail.component.versionRange} imported from ${detail.source ?? \"an undefined source\"}.`\n );\n this.component = new ComponentPath(detail.component);\n } else {\n super(\n `${detail?.cause ?? \"Unknown error\"} in unknown component imported from ${detail?.source ?? \"unknown source\"}.`\n );\n this.component = null;\n }\n\n this.source = detail?.source ?? \"unknown source\";\n this.errors = [];\n if (detail?.error) {\n this.errors?.push(detail?.error);\n }\n if (Error.captureStackTrace) {\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n Error.captureStackTrace(this, CCCError);\n }\n\n this.name = \"CCCError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur during the import of the CCC component app\n */\nexport class CCCImportError extends CCCError {\n constructor(message: string, detail: DetailType) {\n super(message, { ...detail, cause: \"Import error\" });\n this.name = \"CCCImportError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur during the rendering of the CCC component app\n */\nexport class CCCRenderError extends CCCError {\n constructor(message: string, detail: DetailType) {\n super(message, { ...detail, cause: \"Render error\" });\n this.name = \"CCCRenderError\";\n }\n}\n\n/**\n * This class is used to raise errors that occur as a result of the CCC component app timing out\n */\nexport class CCCTimeoutError extends CCCError {\n constructor(detail: DetailType) {\n super(null, { ...detail, cause: \"Timeout error\" });\n this.name = \"CCCTimeoutError\";\n }\n}\n","import { ComponentPath } from \"./path\";\n\nexport class CCCEvent extends Event {\n component: ComponentPath;\n source?: string;\n static eventType = \"ccc:event\";\n\n constructor(\n eventType: string = CCCEvent.eventType,\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(eventType, {\n bubbles: true,\n cancelable: false,\n composed: true,\n ...opts,\n });\n this.component = detail.component;\n this.source = detail.source;\n }\n}\n\nexport class CCCConnectedEvent extends CCCEvent {\n static eventType = \"ccc:connected\";\n\n constructor(\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(CCCConnectedEvent.eventType, detail, opts);\n }\n}\n\nexport class CCCReadyEvent extends CCCEvent {\n static eventType = \"ccc:ready\";\n\n constructor(\n detail: { component: ComponentPath; source?: string },\n opts?: EventInit\n ) {\n super(CCCReadyEvent.eventType, detail, opts);\n }\n}\n\nexport class CCCViewportEvent extends CCCEvent {\n static eventType = \"ccc:viewport\";\n intersecting = false;\n entry?: IntersectionObserverEntry;\n\n constructor(\n detail: {\n component: ComponentPath;\n source?: string;\n intersecting: boolean;\n entry?: IntersectionObserverEntry;\n },\n opts?: EventInit\n ) {\n super(CCCViewportEvent.eventType, detail, opts);\n this.intersecting = detail.intersecting;\n this.entry = detail.entry;\n }\n}\n","/**\n * Used to convert camelCase to kebab-case\n * @param str\n * @returns\n */\nexport const kebabize = (str: string) =>\n str.replace(\n /[A-Z]+(?![a-z])|[A-Z]/g,\n ($, ofs) => (ofs ? \"-\" : \"\") + $.toLowerCase()\n );\n\n/**\n * Checks if the provided host is part of the allowed test environments.\n *\n * @param host - The hostname to check.\n * @returns True if the hostname is a safe test environment, false otherwise.\n */\nexport function isSafeTestEnv(host: string | undefined) {\n return isAllowed([\n 'localhost',\n 'local.ft.com',\n /^.*\\.apps\\.in\\.ft\\.com$/,\n ], host);\n}\n\n/**\n * Checks if the current window location hostname is considered a local environment.\n *\n * @returns True if the hostname is local, false otherwise.\n */\nexport function isLocalEnv() {\n return isAllowed([\n 'localhost',\n 'local.ft.com',\n /^.*\\.in\\.ft\\.com$/,\n ], window.location.hostname);\n}\n\n/**\n * Checks if the current window location host is one of the Spark environments.\n *\n * @returns True if the host is spark.ft.com or spark-staging.ft.com, false otherwise.\n */\nexport function isSparkEnv() {\n return isAllowed([\n 'spark.ft.com',\n 'spark-staging.ft.com',\n ], window.location.host);\n}\n\n/**\n * Checks if the given hostname is in the provided allowlist.\n *\n * @param allowlist - A list of allowed hostnames or RegExp matchers.\n * @param hostname - The hostname to validate.\n * @returns True if the hostname matches any item in the allowlist, false otherwise.\n */\nexport function isAllowed(allowlist: (string|RegExp)[], hostname: string | undefined) {\n if (!hostname) return false;\n return allowlist.some(item => {\n if (typeof item === 'string') {\n return item === hostname;\n }\n return item.test(hostname);\n });\n} \n","import { isLocalEnv, isSafeTestEnv, isSparkEnv } from \"./util\";\n\n/**\n * Assigns a test URL based on the provided testEnv value.\n *\n * @param testEnv - A string indicating test environment setting\n * @returns A `URL` object if valid and safe, or `undefined` if invalid.\n */\nexport function assignTestURL(testEnv: string | null): URL | undefined {\n if (testEnv === null) {\n return;\n }\n\n let testUrl;\n const defaultTestUrl = new URL(\"http://localhost:5173\");\n\n try {\n if (typeof testEnv === \"string\") {\n if (\n (testEnv === \"\" || testEnv.toLowerCase() === \"true\") &&\n isLocalEnv()\n ) {\n testUrl = defaultTestUrl;\n } else {\n const hasProtocol =\n testEnv.startsWith(\"http://\") || testEnv.startsWith(\"https://\");\n testUrl = hasProtocol ? new URL(testEnv) : undefined;\n\n // Prevent script injection\n if (testUrl && !isSafeTestEnv(testUrl?.hostname)) {\n throw new Error(\"Unsafe testing host override\");\n }\n }\n } else if (isSparkEnv()) {\n testUrl = defaultTestUrl;\n }\n } catch (_) {\n return testUrl;\n }\n\n return testUrl;\n}\n\n/**\n * Checks whether the given test component exists on local dev server\n *\n * @param testUrl - The test environment URL to check.\n * @returns A promise that resolves to true if Vite is running, false otherwise.\n */\nexport async function useComponentTestEnv(\n componentName: string,\n testUrl?: URL\n): Promise<boolean> {\n if (!testUrl) {\n return false;\n }\n\n const localDevOnline = fetch(\n new URL(`src/${componentName}/config.yaml`, testUrl),\n {\n method: \"HEAD\",\n }\n )\n .then(() => true)\n .catch(() => false);\n\n return localDevOnline;\n}\n","/**\n * @file\n * Main component definition for custom-code-component\n */\n\nimport type { ContentTree } from \"@financial-times/content-tree\";\nimport type { BaseRenderer } from \"../../ccc-sdk/src/renderers/BaseRenderer\";\nimport Tracking from \"./tracking\";\nimport { Logger, LogLevel } from \"./logger\";\nimport {\n CCCError,\n CCCImportError,\n CCCRenderError,\n CCCTimeoutError,\n} from \"./errors\";\nimport { CCCConnectedEvent, CCCReadyEvent, CCCViewportEvent } from \"./events\";\nimport { ComponentPath } from \"./path\";\nimport { kebabize } from \"./util\";\nimport { assignTestURL, useComponentTestEnv } from \"./environment\";\nimport styles from \"./custom-code-component.css?inline\";\n\nexport class FTCustomCodeComponent extends HTMLElement {\n /**\n * The component renderer, resolved from dynamic import\n */\n app?: typeof BaseRenderer.prototype.render;\n\n /**\n * Set whether component is \"open\" or \"closed\". Defaults to \"open\".\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#mode\n */\n mode: \"closed\" | \"open\" = \"open\";\n\n /**\n * Reserved attributes we don't pass to the child component\n */\n RESERVED_ATTRS = new Set([\n \"iframe\",\n \"path\",\n \"version\",\n \"data-component-props\",\n \"data-asset-type\",\n \"shadow-open\",\n \"env\",\n \"load-timeout\",\n ]);\n\n /**\n * URI of component module for CCC webcomponent to load\n */\n source?: string;\n\n /**\n * OTracking config\n */\n tracking?: Tracking;\n\n /**\n * Alternative base URL, used for testing\n */\n testUrl?: URL;\n\n /**\n * ComponentPath instance with `org`, `repo`, `name` and `versionRange` attributes\n */\n component = new ComponentPath();\n\n /**\n * Logger instance. Set log level using `this.logger.setLogLevel(string|number|null)`.\n */\n logger: Logger;\n\n /**\n * Abort controller used to abort async connectedCallback functionality when disconnectedCallback is called`.\n */\n ac: AbortController | null = null;\n\n /**\n * IntersectionObserver that dispatches CCCViewportEvents\n */\n observer = new IntersectionObserver((entries) => {\n this.logger.debug(\"Intersection Observer callback\", { entries });\n entries.forEach((entry) => {\n this.dispatchEvent(\n new CCCViewportEvent({\n component: this.component,\n source: this.source,\n intersecting: entry.isIntersecting,\n entry,\n }),\n );\n });\n });\n\n /**\n * Custom Element constructor.\n *\n * n.b., attributes and ShadowDOM aren't available in custom element constructors.\n * Use connectedCallback() and other lifecycle methods if you want to eg. this.getAttribute()\n */\n constructor() {\n super();\n this.logger = new Logger();\n\n const supportsDeclarative =\n HTMLElement.prototype.hasOwnProperty(\"attachInternals\");\n\n try {\n const internals = supportsDeclarative && this.attachInternals();\n } catch (e) {\n this.logger.error(e);\n }\n }\n\n /**\n * connectedCallback() CE lifecycle callback\n *\n * Called whenever a <custom-code-component> element is mounted to the DOM.\n */\n async connectedCallback() {\n try {\n const path = this.getAttribute(\"path\");\n const versionRange = this.getAttribute(\"version\");\n this.component = ComponentPath.fromString(path, versionRange);\n this.logger.component = this.component;\n this.logger.setLogLevel(this.getAttribute(\"log\"));\n this.logger.debug(\"connectedCallback\");\n this.ac?.abort();\n this.ac = new AbortController();\n this.app = await this.load(this.ac.signal);\n this.mount();\n this.initTracking();\n } catch (e) {\n if (e instanceof Error) {\n requestAnimationFrame(() => {\n this.emitError(e);\n });\n }\n\n this.unmount(e as Error);\n }\n }\n\n /**\n * Error handler. Decorates errors for easier ingestion.\n *\n * @param error\n */\n emitError(error: Error) {\n this.logger.debug(\"emitError\", { error });\n if (error instanceof CCCError) {\n this.dispatchEvent(\n new ErrorEvent(\"ccc:error\", {\n bubbles: true,\n cancelable: false,\n composed: true,\n error,\n message: error.message,\n }),\n );\n } else {\n // Wrap original error with generic CCC error class\n const wrappedError = new CCCError(error.message, {\n component: this.component,\n error: error,\n });\n\n this.dispatchEvent(\n new ErrorEvent(\"ccc:error\", {\n bubbles: true,\n cancelable: false,\n composed: true,\n error: wrappedError,\n message: wrappedError.message,\n }),\n );\n }\n }\n\n /**\n * disconnectedCallback() CE lifecycle event.\n *\n * Called when a <custom-code-component> element is removed from DOM.\n */\n disconnectedCallback() {\n this.ac?.abort();\n this.logger.debug(\"disconnectedCallback\");\n const path = this.getAttribute(\"path\");\n this.destroyTracking();\n this.logger.info(`<custom-code-component:${path}> disconnected`);\n this.observer.disconnect();\n }\n\n /**\n * MessageChannel interface.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel\n */\n channel = new MessageChannel();\n\n /**\n * MessageChannel postMessage callback\n *\n * @param e\n */\n onmessage(e?: any) {\n this.logger.debug(\"onmessage\", { event: e });\n }\n\n /**\n * This error handler is called by the child component on e.g. unrecoverable error.\n * It then calls unmount(), which restores the fallback.\n *\n * @param e\n */\n onunmount(e: Error) {\n this.logger.debug(\"onunmount\", { error: e });\n if (e instanceof Error) {\n const renderError = new CCCRenderError(e.message, {\n error: e,\n component: this.component,\n });\n requestAnimationFrame(() => {\n this.emitError(renderError);\n this.unmount(renderError);\n });\n }\n }\n\n /**\n * onready event callback.\n * Called by mount() after kicking off initial component render.\n *\n * @param app\n */\n async onready(app: Promise<void>) {\n try {\n await app;\n this.logger.debug(\"onready\", { app });\n this.dispatchEvent(\n new CCCReadyEvent({\n component: this.component,\n source: this.source,\n }),\n );\n\n this.dataset.cccReady = \"true\";\n delete this.dataset.cccError;\n\n this.observer.observe(this);\n } catch (e) {\n this.logger.debug(\"onready caught error\", { error: e });\n if (e instanceof Error) {\n const renderError = new CCCRenderError(e.message, {\n error: e,\n component: this.component,\n });\n requestAnimationFrame(() => {\n this.emitError(renderError);\n this.unmount(renderError);\n });\n }\n }\n }\n\n /**\n * MessageChannel postMessage handler.\n * This can be used for inter-CCC communication.\n * @param event\n */\n postMessage(event: any) {\n this.logger.debug(\"postmessage\", { event });\n this.channel.port1.postMessage(event);\n }\n\n /**\n * Initial mounting behaviour.\n *\n * Attaches ShadowDOM if needed, dispatches ccc:connected event, adds component base styles,\n * generates fallback template element if one doesn't exist already, initialises tracking,\n * then kicks off component rendering. Passes component render promise to onready().\n *\n * @param prerendered\n */\n mount(prerendered?: ShadowRoot | null) {\n this.logger.debug(\"mount\", prerendered);\n try {\n this.mode =\n this.getAttribute(\"shadow-open\") == \"false\" ? \"closed\" : \"open\";\n if (this.component) {\n if (!this.app) {\n throw new Error(\"CCC mounted without App\");\n }\n\n const ssr = this.shadowRoot !== null;\n const shadow =\n this.shadowRoot ?? this.attachShadow({ mode: this.mode });\n\n this.dispatchEvent(\n new CCCConnectedEvent({\n component: this.component,\n source: this.source,\n }),\n );\n // Add global CCC styles if not already present in shadow DOM.\n if (\n !shadow.querySelector('link[href~=\"custom-code-component.css\"]') &&\n !shadow.adoptedStyleSheets.length\n ) {\n if (!window.CCC_LAYOUT_STYLESHEET) {\n this.logger.debug(\"mount generating CCC_LAYOUT_STYLESHEET\");\n window.CCC_LAYOUT_STYLESHEET = new CSSStyleSheet();\n window.CCC_LAYOUT_STYLESHEET.replaceSync(styles);\n }\n shadow.adoptedStyleSheets = [window.CCC_LAYOUT_STYLESHEET];\n }\n\n if (!ssr) {\n this.logger.debug(\"mount generating fallback template\");\n const template = document.createElement(\"template\");\n template.innerHTML = \"<div data-component-root><slot></slot></div>\";\n this.appendChild(template);\n shadow.appendChild(template.content.cloneNode(true));\n }\n\n const data = JSON.parse(this.getAttribute(\"data-component-props\")!);\n\n const extraProps = Object.fromEntries(\n [...this.attributes]\n .filter(\n (attribute) =>\n !this.RESERVED_ATTRS.has(attribute.name) &&\n !attribute.name.startsWith(\"data-\"),\n )\n .map((attribute) => [attribute.name, attribute.value]),\n );\n\n // Create tracking instance\n this.tracking = new Tracking({\n name: this.component?.toString(),\n subtype: \"interactive\",\n teamName: \"djd\",\n shadowRoot: this.shadowRoot,\n logger: this.logger,\n });\n\n if (!data && Object.keys(extraProps).length > 0) {\n this.logger.warn(\n \"passing component settings as webcomponent attributes is %cDEPRECATED%c and will be removed in v3.\",\n \"font-weight: bold\",\n \"\",\n );\n this.logger.warn(\n \"Please use the %cdata-component-props%c attribute instead.\",\n \"text-decoration: underline;\",\n \"\",\n );\n }\n\n const { onmessage, ready = Promise.resolve() } =\n this.app(\n shadow,\n {\n ...(data ?? extraProps),\n log: this.logger,\n data: data ?? extraProps,\n port: this.channel.port2,\n tracking: this.tracking,\n prerendered: !!prerendered,\n children: this.children,\n },\n ssr,\n this.onunmount.bind(this),\n ) || {};\n\n if (onmessage) this.onmessage = onmessage;\n\n this.onready(ready);\n }\n } catch (err) {\n this.logger.info(\n `<custom-code-component> uncaught error during mount from ${this.component?.toString()}`,\n );\n this.logger.error(err);\n\n throw err;\n }\n }\n\n /**\n * Called in top-level error handler or by child component on unhandled error.\n * Replace shadow root with either <slot> or template[data-component-fallback]\n * slot on failure\n *\n * @param e\n */\n unmount(e: Error) {\n this.logger.debug(\"unmount\", { error: e });\n\n const template =\n this.querySelector<HTMLTemplateElement>(\n \"template[data-component-fallback]\",\n ) ?? this.querySelector<HTMLTemplateElement>(\"template\");\n\n if (template) {\n this.logger.debug(\"unmount replacing shadowRoot with fallback\");\n this.shadowRoot?.replaceChildren(template.content.cloneNode(true));\n }\n\n if (!this.dataset.cccError)\n this.dataset.cccError = kebabize(e.name.replace(\"CCC\", \"\"));\n\n delete this.dataset.cccReady;\n\n this.observer.disconnect();\n }\n\n /**\n * Asynchronously loads the CCC child component.\n *\n * @returns Promise resolving to component renderer function\n */\n async load(signal: AbortSignal) {\n this.logger.debug(\"load\");\n\n if (!this.component.isValid) {\n throw new Error(\"No path found\");\n }\n\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n const timeout = Number(this.getAttribute(\"load-timeout\") || 10000);\n const testEnv = this.getAttribute(\"test-env\");\n this.testUrl = assignTestURL(testEnv);\n const isTestEnv = await useComponentTestEnv(\n this.component.name,\n this.testUrl,\n );\n\n // id querystring necessary to multiple allow components with the same source (same name and version number) to appear on the page correctly\n const id = this.getAttribute(\"id\");\n\n if (isTestEnv && this.testUrl) {\n this.logger.debug(\"load adding Vite scripts\");\n this.injectViteScripts();\n }\n\n this.source = isTestEnv\n ? `${this.testUrl?.origin}/src/${this.component.name}/index.jsx?id=${id}`\n : `https://www.ft.com/__component/${this.component.org}/${this.component.repo}${\n componentVersionRange ? `@${componentVersionRange}` : \"@latest\"\n }/${this.component.name}/${this.component.name}.js?id=${id}`;\n\n try {\n return await new Promise<typeof BaseRenderer.prototype.render>(\n (resolve, reject) => {\n signal.throwIfAborted();\n const to = setTimeout(() => {\n this.logger.error(\"CCC import timeout error\");\n reject(\n new CCCTimeoutError({\n component: this.component!,\n source: this.source,\n }),\n );\n }, Number(timeout));\n\n if (this.source) {\n import(/* webpackIgnore: true */ this.source /* @vite-ignore */)\n .then(({ default: componentRenderFunction }) => {\n if (componentRenderFunction) {\n clearTimeout(to);\n resolve(componentRenderFunction);\n } else\n throw new CCCImportError(\n \"No component renderer default export found\",\n {\n component: this.component!,\n source: this.source,\n },\n );\n })\n .catch((e) => {\n clearTimeout(to);\n this.logger.error(e);\n if (e instanceof Error && !(e instanceof CCCImportError)) {\n reject(\n new CCCImportError(e.message, {\n component: this.component!,\n source: this.source,\n }),\n );\n } else {\n reject(e);\n }\n });\n } else {\n clearTimeout(to);\n throw new CCCImportError(`Unable to mount ${path}`, {\n component: this.component!,\n source: this.source,\n });\n }\n\n signal.addEventListener(\n \"abort\",\n () => {\n // Stop the main operation\n // Reject the promise with the abort reason.\n reject(signal.reason);\n },\n { once: true },\n );\n },\n );\n } catch (err) {\n this.logger.error(\n `<custom-code-component> error during import from ${path}@${componentVersionRange}`,\n );\n\n throw err;\n }\n }\n\n /**\n * Initialises OTracking\n */\n initTracking = () => {\n this.logger.debug(\"initTracking\", { cccId: this.id });\n try {\n this.tracking?.init(this.id);\n } catch (e) {\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n this.logger.info(\n `Error initialising tracking on <custom-code-component> ${path}@${componentVersionRange}`,\n );\n this.logger.error(e);\n }\n };\n\n /**\n * Destroys OTracking to avoid duplicate events\n */\n destroyTracking = () => {\n this.logger.debug(\"destroyTracking\", { cccId: this.id });\n try {\n this.tracking?.destroy();\n } catch (e) {\n const path = this.getAttribute(\"path\");\n const componentVersionRange = this.getAttribute(\"version\");\n this.logger.info(\n `Error destroying tracking on <custom-code-component> ${path}@${componentVersionRange}`,\n );\n this.logger.error(e);\n }\n };\n\n /**\n * Injects Vite HMR scripts during dev environment usage\n */\n injectViteScripts = () => {\n if (document.querySelector('script[name=\"ccc-sdk-react-preamble\"]')) return;\n\n const preambleScript = document.createElement(\"script\");\n preambleScript.type = \"module\";\n preambleScript.setAttribute(\"name\", \"ccc-sdk-react-preamble\");\n\n preambleScript.textContent = `\n import RefreshRuntime from \"${this.testUrl?.origin}/@react-refresh\";\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n `.trim();\n document.head.appendChild(preambleScript);\n\n const viteClientScript = document.createElement(\"script\");\n viteClientScript.type = \"module\";\n viteClientScript.src = `${this.testUrl?.origin}/@vite/client`;\n document.head.appendChild(viteClientScript);\n };\n\n /**\n * Called whenever the <custom-code-component>'s attributes are changed.\n * Currently only used to dynamically set log level.\n *\n * @param name\n * @param oldValue\n * @param newValue\n */\n attributeChangedCallback(name: string, oldValue: string, newValue: string) {\n this.logger.debug(\"attributeChangedCallback lifecycle method\", {\n name,\n oldValue,\n newValue,\n });\n\n switch (name) {\n case \"log\": {\n this.logger.setLogLevel(newValue);\n }\n }\n }\n}\n\nexport interface CustomCodeComponent extends ContentTree.Node {\n type: \"CustomCodeComponent\";\n path: string;\n versionRange: string;\n altText: string;\n lastModified: string;\n fallbackImage?: ContentTree.Image;\n displayFallbackText: boolean;\n layout: \"in-line\" | \"mid-grid\" | \"full-grid\" | \"full-bleed\";\n /* prettier-ignore */\n attributes: {\n [key: string]: string | boolean | undefined;\n } | { children?: CustomCodeComponent | Array<CustomCodeComponent> };\n}\n\nexport type { FTCustomCodeComponent as CCCHTMLElement };\n"],"names":["Delegate","root","listenerMap","eventType","selector","handler","useCapture","matcher","matcherParam","matchesTag","matchesId","matchesRoot","i","listener","listenerList","singleEventType","event","l","type","phase","returned","target","eventIgnore","toFire","ret","tagName","element","id","sanitise","str","assignIfUndefined","subject","prop","LogLevel","LOG_PREFIX","convertStringLogLevel","value","level","Logger","component","args","suffix","first","rest","getSiblingsAndPosition","el","originalEl","siblings","position","item","elementPropertiesToCollect","getAllElementProperties","properties","property","parseRawValue","rawValue","parsedValue","getAttributeValue","isJSON","getDomPathProps","attrs","props","attribute","getContextProps","isOriginalEl","customProps","name","getTrace","rootEl","trace","customContext","domPathProps","contextProps","eventPropertiesToCollect","Tracking","subtype","teamName","shadowRoot","category","elements","logger","eventProperties","e","eventData","clickEvent","clickElement","context","triggerAction","extraDetail","_a","ComponentPath","path","org","repo","versionRange","isValidComponentPathObject","p","v","CCCError","message","detail","CCCImportError","CCCRenderError","CCCTimeoutError","_CCCEvent","opts","CCCEvent","_CCCConnectedEvent","CCCConnectedEvent","_CCCReadyEvent","CCCReadyEvent","_CCCViewportEvent","CCCViewportEvent","kebabize","$","ofs","isSafeTestEnv","host","isAllowed","isLocalEnv","isSparkEnv","allowlist","hostname","assignTestURL","testEnv","testUrl","defaultTestUrl","useComponentTestEnv","componentName","FTCustomCodeComponent","entries","entry","componentVersionRange","_b","preambleScript","viteClientScript","supportsDeclarative","internals","error","wrappedError","renderError","app","prerendered","ssr","shadow","styles","template","data","extraProps","onmessage","ready","err","signal","timeout","isTestEnv","resolve","reject","to","componentRenderFunction","oldValue","newValue"],"mappings":"AAUA,SAASA,EAASC,GAAM;AAQvB,OAAK,cAAc,CAAC,CAAE,GAAE,EAAE,GACtBA,KACH,KAAK,KAAKA,CAAI,GAIf,KAAK,SAASD,EAAS,UAAU,OAAO,KAAK,IAAI,GAGjD,KAAK,oBAAoB,CAAE;AAC5B;AASAA,EAAS,UAAU,OAAO,SAAUC,GAAM;AACzC,QAAMC,IAAc,KAAK;AACzB,MAAIC;AAGJ,MAAI,KAAK,aAAa;AACrB,SAAKA,KAAaD,EAAY,CAAC;AAC9B,MAAIA,EAAY,CAAC,EAAE,eAAeC,CAAS,KAC1C,KAAK,YAAY,oBAAoBA,GAAW,KAAK,QAAQ,EAAI;AAGnE,SAAKA,KAAaD,EAAY,CAAC;AAC9B,MAAIA,EAAY,CAAC,EAAE,eAAeC,CAAS,KAC1C,KAAK,YAAY,oBAAoBA,GAAW,KAAK,QAAQ,EAAK;AAAA,EAGtE;AAKC,MAAI,CAACF,KAAQ,CAACA,EAAK;AAClB,WAAI,KAAK,eACR,OAAO,KAAK,aAEN;AASR,OAAK,cAAcA;AAGnB,OAAKE,KAAaD,EAAY,CAAC;AAC9B,IAAIA,EAAY,CAAC,EAAE,eAAeC,CAAS,KAC1C,KAAK,YAAY,iBAAiBA,GAAW,KAAK,QAAQ,EAAI;AAGhE,OAAKA,KAAaD,EAAY,CAAC;AAC9B,IAAIA,EAAY,CAAC,EAAE,eAAeC,CAAS,KAC1C,KAAK,YAAY,iBAAiBA,GAAW,KAAK,QAAQ,EAAK;AAIjE,SAAO;AACR;AAMAH,EAAS,UAAU,iBAAiB,SAAUG,GAAW;AACxD,SAAO,CAAC,QAAQ,SAAS,SAAS,QAAQ,UAAU,QAAQ,EAAE,QAAQA,CAAS,MAAM;AACtF;AA2BAH,EAAS,UAAU,KAAK,SAAUG,GAAWC,GAAUC,GAASC,GAAY;AAC3E,MAAIL,GACAC,GACAK,GACAC;AAEJ,MAAI,CAACL;AACJ,UAAM,IAAI,UAAU,yBAAyBA,CAAS;AAiBvD,MAZI,OAAOC,KAAa,eACvBE,IAAaD,GACbA,IAAUD,GACVA,IAAW,OAKRE,MAAe,WAClBA,IAAa,KAAK,eAAeH,CAAS,IAGvC,OAAOE,KAAY;AACtB,UAAM,IAAI,UAAU,oCAAoC;AAGzD,SAAAJ,IAAO,KAAK,aACZC,IAAc,KAAK,YAAYI,IAAa,IAAI,CAAC,GAG5CJ,EAAYC,CAAS,MACrBF,KACHA,EAAK,iBAAiBE,GAAW,KAAK,QAAQG,CAAU,GAEzDJ,EAAYC,CAAS,IAAI,CAAE,IAGvBC,IAQM,YAAY,KAAKA,CAAQ,KACnCI,IAAeJ,GACfG,IAAUE,KACA,mBAAmB,KAAKL,CAAQ,KAC1CI,IAAeJ,EAAS,MAAM,CAAC,GAC/BG,IAAUG,MAEVF,IAAeJ,GACfG,IAAU,QAAQ,UAAU,YAf5BC,IAAe,MAIfD,IAAUI,EAAY,KAAK,IAAI,IAehCT,EAAYC,CAAS,EAAE,KAAK;AAAA,IAC3B,UAAUC;AAAA,IACV,SAASC;AAAA,IACT,SAASE;AAAA,IACT,cAAcC;AAAA,EAChB,CAAE,GAEM;AACR;AAYAR,EAAS,UAAU,MAAM,SAAUG,GAAWC,GAAUC,GAASC,GAAY;AAC5E,MAAIM,GACAC,GACAX,GACAY,GACAC;AAYJ,MARI,OAAOX,KAAa,eACvBE,IAAaD,GACbA,IAAUD,GACVA,IAAW,OAKRE,MAAe;AAClB,gBAAK,IAAIH,GAAWC,GAAUC,GAAS,EAAI,GAC3C,KAAK,IAAIF,GAAWC,GAAUC,GAAS,EAAK,GACrC;AAIR,MADAH,IAAc,KAAK,YAAYI,IAAa,IAAI,CAAC,GAC7C,CAACH,GAAW;AACf,SAAKY,KAAmBb;AACvB,MAAIA,EAAY,eAAea,CAAe,KAC7C,KAAK,IAAIA,GAAiBX,GAAUC,CAAO;AAI7C,WAAO;AAAA,EACT;AAGC,MADAS,IAAeZ,EAAYC,CAAS,GAChC,CAACW,KAAgB,CAACA,EAAa;AAClC,WAAO;AAKR,OAAKF,IAAIE,EAAa,SAAS,GAAGF,KAAK,GAAGA;AACzC,IAAAC,IAAWC,EAAaF,CAAC,IAEpB,CAACR,KAAYA,MAAaS,EAAS,cAAc,CAACR,KAAWA,MAAYQ,EAAS,aACtF,KAAK,kBAAkB,KAAKA,CAAQ,GACpCC,EAAa,OAAOF,GAAG,CAAC;AAK1B,SAAKE,EAAa,WACjB,OAAOZ,EAAYC,CAAS,GAGxB,KAAK,eACR,KAAK,YAAY,oBAAoBA,GAAW,KAAK,QAAQG,CAAU,IAIlE;AACR;AAQAN,EAAS,UAAU,SAAS,SAAUgB,GAAO;AAC5C,MAAIJ,GACAK;AACJ,QAAMC,IAAOF,EAAM;AACnB,MAAIf,GACAkB,GACAN,GACAO,GACAN,IAAe,CAAE,GACjBO;AACJ,QAAMC,IAAc;AAEpB,MAAIN,EAAMM,CAAW,MAAM;AAC1B;AAqBD,UAlBAD,IAASL,EAAM,QAIXK,EAAO,aAAa,MACvBA,IAASA,EAAO,aAIbA,EAAO,4BACVA,IAASA,EAAO,0BAGjBpB,IAAO,KAAK,aAEZkB,IAAQH,EAAM,eAAeA,EAAM,WAAWA,EAAM,gBAAgB,IAAI,IAGhEG,GAAK;AAAA,IACZ,KAAK;AACJ,MAAAL,IAAe,KAAK,YAAY,CAAC,EAAEI,CAAI;AACvC;AAAA,IACD,KAAK;AACJ,MAAI,KAAK,YAAY,CAAC,KAAK,KAAK,YAAY,CAAC,EAAEA,CAAI,MAClDJ,IAAeA,EAAa,OAAO,KAAK,YAAY,CAAC,EAAEI,CAAI,CAAC,IAEzD,KAAK,YAAY,CAAC,KAAK,KAAK,YAAY,CAAC,EAAEA,CAAI,MAClDJ,IAAeA,EAAa,OAAO,KAAK,YAAY,CAAC,EAAEI,CAAI,CAAC;AAE7D;AAAA,IACD,KAAK;AACJ,MAAAJ,IAAe,KAAK,YAAY,CAAC,EAAEI,CAAI;AACvC;AAAA,EACH;AAEC,MAAIK,IAAS,CAAE;AAQf,OADAN,IAAIH,EAAa,QACVO,KAAUJ,KAAG;AACnB,SAAKL,IAAI,GAAGA,IAAIK,MACfJ,IAAWC,EAAaF,CAAC,GAMrB,EAACC,IAPaD;AAWlB,MACCS,EAAO,WACP,CAAC,UAAU,SAAS,UAAU,UAAU,EAAE,QAAQA,EAAO,QAAQ,YAAa,CAAA,IAAI,MAClFA,EAAO,aAAa,UAAU,IAG9BE,IAAS,CAAE,IAQHV,EAAS,QAAQ,KAAKQ,GAAQR,EAAS,cAAcQ,CAAM,KACnEE,EAAO,KAAK,CAACP,GAAOK,GAAQR,CAAQ,CAAC;AAmBvC,QAVIQ,MAAWpB,MAIfgB,IAAIH,EAAa,QAGjBO,IAASA,EAAO,iBAAiBA,EAAO,YAGpCA,aAAkB;AACrB;AAAA,EAEH;AAEC,MAAIG;AAEJ,OAAKZ,IAAI,GAAGA,IAAIW,EAAO,QAAQX;AAE9B,QAAI,OAAK,kBAAkB,QAAQW,EAAOX,CAAC,EAAE,CAAC,CAAC,IAAI,QAGnDQ,IAAW,KAAK,KAAK,MAAM,MAAMG,EAAOX,CAAC,CAAC,GAKtCQ,MAAa,KAAO;AACvB,MAAAG,EAAOX,CAAC,EAAE,CAAC,EAAEU,CAAW,IAAI,IAC5BC,EAAOX,CAAC,EAAE,CAAC,EAAE,eAAgB,GAC7BY,IAAM;AACN;AAAA,IACH;AAGC,SAAOA;AACR;AAUAxB,EAAS,UAAU,OAAO,SAAUgB,GAAOK,GAAQR,GAAU;AAC5D,SAAOA,EAAS,QAAQ,KAAKQ,GAAQL,GAAOK,CAAM;AACnD;AAcA,SAASZ,EAAWgB,GAASC,GAAS;AACrC,SAAOD,EAAQ,YAAW,MAAOC,EAAQ,QAAQ,YAAa;AAC/D;AAUA,SAASf,EAAYP,GAAUsB,GAAS;AACvC,SAAI,KAAK,gBAAgB;AAAA;AAAA,IAGvBA,MAAY;AAAA,IAEZA,MAAY,SAAS;AAAA,IAErBA,MAAY;AAAA,MAGP,KAAK,gBAAgBA;AAC7B;AAaA,SAAShB,EAAUiB,GAAID,GAAS;AAC/B,SAAOC,MAAOD,EAAQ;AACvB;AASA1B,EAAS,UAAU,UAAU,WAAY;AACxC,OAAK,IAAK,GACV,KAAK,KAAM;AACZ;AChQA,SAAS4B,EAAUC,GAAK;AACvB,SAAO,OAAOA,KAAQ,WAAWA,EAAI,KAAM,IAAGA;AAC/C;AASA,SAASC,EAAmBC,GAASV,GAAQ;AAC5C,aAAWW,KAAQD;AAClB,IAAKV,EAAOW,CAAI,IAIf,QAAQ,KAAK,0CAA0CA,CAAI,EAAE,IAH7DX,EAAOW,CAAI,IAAID,EAAQC,CAAI;AAM9B;AC/Oa,MAAAC,IAAW,OAAO,OAAO;AAAA,EACpC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AACX,CAAC,GAEKC,IAAa;AAEZ,SAASC,EAAsBC,GAAsB;AACpD,QAAAC,IAAQD,KAAA,gBAAAA,EAAO;AAErB,SAAIC,MAAU,UACLJ,EAAS,QAGdI,MAAU,SACLJ,EAAS,OAGdI,MAAU,SACLJ,EAAS,OAGdI,MAAU,UACLJ,EAAS,QAGdI,MAAU,SACLJ,EAAS,OAGXA,EAAS;AAClB;AAEO,MAAMK,EAAO;AAAA,EAIlB,YACE;AAAA,IACE,OAAAD,IAAQJ,EAAS;AAAA,IACjB,WAAAM;AAAA,EAAA,IACgD;AAAA,IAChD,OAAON,EAAS;AAAA,EAAA,GAElB;AA6BF,SAAA,MAAM,KAAK,OA5BJ,KAAA,QAAQ,qCAAc,QAAQ,mBAC/BE,EAAsB,aAAa,QAAQ,eAAe,CAAC,IAC3DE,GACJ,KAAK,YAAYE;AAAA,EAAA;AAAA,EAGX,kBAAkBC,GAAa;AACrC,UAAMC,IAAS,KAAK,YAAY,CAAC,KAAK,SAAS,IAAI,CAAC;AAEhD,QAAAD,EAAK,WAAW;AACX,aAAA,CAACN,GAAY,GAAGO,CAAM;AAG/B,UAAM,CAACC,GAAO,GAAGC,CAAI,IAAIH;AAErB,WAAA,OAAOE,KAAU,WACZ,CAAC,GAAGR,CAAU,IAAIQ,CAAK,IAAI,GAAGC,GAAM,GAAGF,CAAM,IAG/C,CAACP,GAAYQ,GAAO,GAAGC,GAAM,GAAGF,CAAM;AAAA,EAAA;AAAA,EAG/C,SAASD,GAAa;AAChB,IAAA,KAAK,SAASP,EAAS,SACzB,QAAQ,KAAK,GAAG,KAAK,kBAAkBO,CAAI,CAAC;AAAA,EAC9C;AAAA,EAKF,QAAQA,GAAa;AACf,IAAA,KAAK,SAASP,EAAS,QACzB,QAAQ,KAAK,GAAG,KAAK,kBAAkBO,CAAI,CAAC;AAAA,EAC9C;AAAA,EAGF,QAAQA,GAAa;AACf,IAAA,KAAK,SAASP,EAAS,QACzB,QAAQ,KAAK,GAAG,KAAK,kBAAkBO,CAAI,CAAC;AAAA,EAC9C;AAAA,EAGF,SAASA,GAAa;AAChB,IAAA,KAAK,SAASP,EAAS,SACzB,QAAQ,MAAM,GAAG,KAAK,kBAAkBO,CAAI,CAAC;AAAA,EAC/C;AAAA,EAGF,YAAYH,GAA+B;AACrC,IAAA,qCAAc,QAAQ,mBACxB,KAAK,QAAQF,EAAsB,aAAa,QAAQ,eAAe,CAAC,IAC/D,OAAOE,KAAU,WAC1B,KAAK,QAAQA,IAER,KAAA,QAAQF,EAAsBE,CAAK;AAAA,EAC1C;AAEJ;ACnGA,MAAMO,IAAyB,CAC7BC,GACAC,GACA1C,MACG;AACG,QAAA2C,IAAW,MAAM,MAAKF,KAAA,gBAAAA,EAAI,iBAAiBzC,OAAa,EAAE,GAC1D4C,IAAWD,EAAS,UAAU,CAACE,MAASA,MAASH,CAAU;AACjE,MAAIE,MAAa;AAGV,WAAA;AAAA,MACL,UAAUD,EAAS;AAAA,MACnB,UAAAC;AAAA,IACF;AACF,GAEME,IAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAEMC,IAA0B,CAACzB,MAAiB;AAChD,QAAM0B,IAAsB,CAAC;AAC7B,aAAWC,KAAYH,GAA4B;AAC3C,UAAAd,IACJV,EAAQ2B,CAAQ,KAChB3B,EAAQ,aAAa2B,CAAQ,KAC7B3B,EAAQ,aAAa2B,CAAQ;AAC/B,IAAIjB,MAAU,WACR,OAAOA,KAAU,YACnBgB,EAAWC,CAAQ,IAAIjB,IAEZgB,EAAAC,CAAQ,IAAIzB,EAASQ,CAAK;AAAA,EAEzC;AAGK,SAAAgB;AACT,GAEME,IAAgB,CAACC,MAAqB;AACtC,MAAA;AACI,UAAAC,IAAc,KAAK,MAAMD,CAAQ,GACjCrC,IAAO,OAAO,UAAU,SAAS,KAAKsC,CAAW;AAGhD,WAAA,CAFQtC,MAAS,qBAAqBA,MAAS,kBAEtCsC,CAAW;AAAA,UACb;AACP,WAAA,CAAC,IAAO,IAAI;AAAA,EAAA;AAEvB,GAEMC,IAAoB,CAACF,MAAqB;AAC9C,QAAM,CAACG,GAAQtB,CAAK,IAAIkB,EAAcC,CAAQ;AAE9C,SAAOG,IAAStB,IAAQmB;AAC1B,GAGMI,IAAkB,CAACC,GAAeC,OAGnCD,EAAA;AAAA,EAAO,CAACE,MACPA,EAAU,KAAK,MAAM,kCAAkC;AAAA,EAExD,QAAQ,CAACA,MAAc;AAChB,EAAAD,EAAAC,EAAU,IAAI,IAAIA,EAAU;AAAA,CACnC,GAEID,IAIHE,IAAkB,CACtBH,GACAC,GACAG,MACG;AACH,QAAMC,IAAoC,CAAC;AAG3C,SAAID,KACyBd,EAAA,QAAQ,CAACgB,MAAS;AAC3C,IAAI,OAAOL,EAAMK,CAAI,IAAM,OAAeA,MAAS,SACrCD,EAAAC,CAAI,IAAIL,EAAMK,CAAI;AAAA,EAChC,CACD,GAKAN,EAAA,OAAO,CAACE,MAAcA,EAAU,KAAK,MAAM,2BAA2B,CAAC,EACvE,QAAQ,CAACA,MAAc;AACV,IAAAG,EAAAH,EAAU,KAAK,QAAQ,2BAA2B,EAAE,CAAC,IAC/DL,EAAkBK,EAAU,KAAK;AAAA,EAAA,CACpC,GAEIG;AACT;AAEgB,SAAAE,EAAStB,GAAauB,GAAiB;AACrD,QAAMtB,IAAaD,GACbzC,IAAW0C,KAAA,QAAAA,EAAY,aAAa,oBACtC,oBAAoBA,EAAW,aAAa,gBAAgB,CAAC,OAC7DA,KAAA,gBAAAA,EAAY,UACVuB,IAAQ,CAAC,GACTC,IAAgB,CAAC;AAChB,SAAAzB,KAAMA,MAAOuB,KAAQ;AACpB,UAAAP,IAAQV,EAAwBN,CAAE,GAClCe,IAAQ,MAAM,KAAKf,EAAG,UAAU;AAClC,QAAA0B,IAAeZ,EAAgBC,GAAOC,CAAK;AAI3C,IAAAU,EAAa,gBAAgB,MAC/BA,IAAe,OAAO;AAAA,MACpBA;AAAA,MACA3B,EAAuBC,GAAIC,GAAY1C,CAAQ;AAAA,IACjD,IAGFiE,EAAM,KAAKE,CAAY;AAEvB,UAAMC,IAAeT,EAAgBH,GAAOC,GAAOhB,MAAOC,CAAU;AAEpE,IAAAhB,EAAkB0C,GAAcF,CAAa,GAE7CzB,IAAKA,EAAG;AAAA,EAAA;AAEH,SAAA,EAAE,OAAAwB,GAAO,eAAAC,EAAc;AAChC;ACtIA,MAAMG,IAA2B,CAAC,WAAW,UAAU,YAAY,SAAS;AAE5E,MAAMC,EAAS;AAAA,EAYb,YAAY;AAAA,IACV,IAAA/C,IAAK;AAAA,IACL,MAAAuC,IAAO;AAAA,IACP,SAAAS,IAAU;AAAA,IACV,UAAAC,IAAW;AAAA,IACX,YAAAC,IAAa;AAAA,IACb,UAAAC,IAAW;AAAA,IACX,UAAAC,IAAW;AAAA,IACX,QAAAC;AAAA,EAAA,GAUC;AACD,SAAK,QAAQrD,GACb,KAAK,UAAUuC,GACf,KAAK,UAAUS,GACf,KAAK,WAAWC,GAChB,KAAK,aAAaC,GAClB,KAAK,WAAWC,GAChB,KAAK,WAAWC,GAChB,KAAK,gBAAgB,IAChB,KAAA,MAAMC,KAAU,IAAI1C,EAAO;AAAA,EAAA;AAAA;AAAA,EAIlC,mBAAmBtB,GAAY;AAC7B,UAAMiE,IAAwC,CAAC;AAC/C,eAAW5B,KAAYoB;AACjB,UAAAzD,EAAMqC,CAAQ;AACZ,YAAA;AACF,UAAA4B,EAAgB5B,CAAQ,IAAIzB,EAASZ,EAAMqC,CAAQ,CAAC;AAAA,iBAC7C6B,GAAG;AACL,eAAA,IAAI,KAAKA,CAAC;AAAA,QAAA;AAId,WAAAD;AAAA,EAAA;AAAA;AAAA,EAIT,iBACEE,GACAlF,GACA;AACO,WAAA,CAACmF,GAAmBC,MAA8B;AACjD,YAAAC,IAAe,KAAK,mBAAmBF,CAAU,GACjD,EAAE,OAAAf,GAAO,eAAAC,EAAA,IAAkBH,EAASkB,GAAcpF,CAAI;AACpD,MAAAqF,EAAA,SACND,EAAa,WAAWA,EAAa,QAAQ,SACzC,KAAK,MAAMA,EAAa,QAAQ,MAAM,IACtC,MACNC,EAAQ,gBAAgBjB,GACxBiB,EAAQ,YAAY;AAAA,QAClB,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,GACAA,EAAQ,WAAW,KAAK,UACxBA,EAAQ,MAAM,SAAS,KAEvBxD,EAAkBwC,GAAegB,CAAO,GAExCA,EAAQ,SAAS,qBACjBH,IAAY,EAAE,GAAGA,GAAW,GAAGG,EAAQ,GAGvC,SAAS,KAAK;AAAA,QACZ,IAAI,YAAY,mBAAmB;AAAA,UACjC,QAAQH;AAAA,UACR,SAAS;AAAA,UACT,UAAU;AAAA,QACX,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EAAA;AAAA,EAGF,eAAeI,GAAoBC,GAAkB;AACnD,UAAML,IAAY;AAAA,MAChB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,QACT,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB;AAAA,MACA,UAAU,KAAK;AAAA,MACf,gBAAgBI;AAAA,MAChB,QAAQC;AAAA,MACR,QAAQ;AAAA,IACV;AAGA,aAAS,KAAK;AAAA,MACZ,IAAI,YAAY,mBAAmB;AAAA,QACjC,QAAQL;AAAA,QACR,SAAS;AAAA,QACT,UAAU;AAAA,MACX,CAAA;AAAA,IACH;AAAA,EAAA;AAAA,EAGF,KAAKxD,GAAY;AJpInB,QAAA8D;AIqIQ,QAAA,CAAC,KAAK,eAAe;AACvB,WAAK,gBAAgB,IAChB,KAAA,QAAQ9D,KAAU,KAAK;AAE5B,YAAMwD,IAAY;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU,KAAK;AAAA,MACjB,GAEMlF,KAAOwF,IAAA,KAAK,eAAL,gBAAAA,EAAiB,cAAc;AAE5C,MAAIxF,MACG,KAAA,iBAAiB,IAAID,EAASC,CAAI,GACvC,KAAK,eAAe;AAAA,QAClB;AAAA,QACA,KAAK;AAAA,QACL,KAAK,iBAAiBkF,GAAWlF,CAAI;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAGF,UAAU;AJ5JZ,QAAAwF;AI6JI,KAAAA,IAAA,KAAK,mBAAL,QAAAA,EAAqB;AAAA,EAAI;AAE7B;ACvJO,MAAMC,EAAc;AAAA,EAMzB,YAAYC,GAAmC;AALjC,SAAA,MAAA,SACC,KAAA,OAAA;AAKb,UAAM,EAAE,KAAAC,GAAK,MAAAC,GAAM,MAAA3B,GAAM,cAAA4B,EAAa,IAAIC,EAA2BJ,CAAI,IACrEA,IACAD,EAAc,WAAWC,CAAI;AAC7B,IAAAC,WAAU,MAAMA,IAChBC,WAAW,OAAOA,IACtB,KAAK,OAAO3B,GACZ,KAAK,eAAe4B;AAAA,EAAA;AAAA,EAGtB,IAAI,KAAKH,GAAkC;AACzC,UAAM,EAAE,KAAAC,GAAK,MAAAC,GAAM,MAAA3B,GAAM,cAAA4B,EAAa,IAAIC,EAA2BJ,CAAI,IACrEA,IACAD,EAAc,WAAWC,CAAI;AACjC,SAAK,MAAMC,GACX,KAAK,OAAOC,GACZ,KAAK,OAAO3B,GACZ,KAAK,eAAe4B;AAAA,EAAA;AAAA,EAGtB,IAAI,OAAe;AACV,WAAA,GAAG,KAAK,GAAG,IAAI,KAAK,IAAI,IAAI,KAAK,YAAY,IAAI,KAAK,IAAI;AAAA,EAAA;AAAA,EAGnE,IAAI,UAAmB;AACrB,WAAO,CAAC,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,EAAE;AAAA,MACtC,CAAC1D,MAAUA,MAAU;AAAA,IACvB;AAAA,EAAA;AAAA,EAGF,WAAmB;AACjB,WAAO,KAAK;AAAA,EAAA;AAAA,EAGd,OAAO,WAAW4D,GAAmBC,GAAkC;ALhDzE,QAAAR;AKiDI,UAAME,IAAOK,KAAK,2BAEZ,CAAC9B,GAAM2B,GAAMD,CAAG,IAAID,EACvB,QAAQ,WAAW,EAAE,EACrB,MAAM,GAAG,EACT,QAAQ,GAELG,IACJG,OACAR,IAAAE,EACG,MAAM,SAAS,MADlB,gBAAAF,EAEI,WACD,QAAQ,KAAK,QAChB;AAEF,QAAII,KAAQ,CAACC,EAAoB,OAAA,IAAII,EAAS,sBAAsB;AAEpE,WAAO,IAAIR,EAAc,EAAE,KAAAE,GAAK,MAAAC,GAAM,MAAA3B,GAAM,cAAA4B,GAAc;AAAA,EAAA;AAE9D;AASO,SAASC,EACd3D,GAC4B;AAC5B,SAAI,OAAOA,KAAU,YAAYA,MAAU,OAClC,SAASA,KAAS,UAAUA,KAAS,UAAUA,IAGjD;AACT;AC/EO,MAAM8D,UAAiB,MAAM;AAAA,EAIlC,YAAYC,GAAwBC,GAAqB;ANV3D,QAAAX;AMWQ,IAAA,CAACW,KAAUD,KACb,MAAMA,CAAO,GACb,KAAK,YAAY,QACR,QAAOC,KAAA,gBAAAA,EAAQ,cAAc,YACtC;AAAA,MACED,KACE,GAAGC,EAAO,SAAS,eAAe,OAAOA,EAAO,SAAS,kBAAkBA,EAAO,UAAU,qBAAqB;AAAA,IACrH,GAEA,KAAK,YAAYV,EAAc,WAAWU,EAAO,SAAS,KACjDL,EAA2BK,KAAA,gBAAAA,EAAQ,SAAS,KACrD;AAAA,MACED,KACE,GAAGC,EAAO,SAAS,eAAe,OAAOA,EAAO,UAAU,GAAG,IAAIA,EAAO,UAAU,IAAI,IAAIA,EAAO,UAAU,IAAI,IAAIA,EAAO,UAAU,YAAY,kBAAkBA,EAAO,UAAU,qBAAqB;AAAA,IAC5M,GACA,KAAK,YAAY,IAAIV,EAAcU,EAAO,SAAS,MAEnD;AAAA,MACE,IAAGA,KAAA,gBAAAA,EAAQ,UAAS,eAAe,wCAAuCA,KAAA,gBAAAA,EAAQ,WAAU,gBAAgB;AAAA,IAC9G,GACA,KAAK,YAAY,OAGd,KAAA,UAASA,KAAA,gBAAAA,EAAQ,WAAU,kBAChC,KAAK,SAAS,CAAC,GACXA,KAAA,QAAAA,EAAQ,WACLX,IAAA,KAAA,WAAA,QAAAA,EAAQ,KAAKW,KAAA,gBAAAA,EAAQ,SAExB,MAAM,qBAEF,MAAA,kBAAkB,MAAMF,CAAQ,GAGxC,KAAK,OAAO;AAAA,EAAA;AAEhB;AAKO,MAAMG,UAAuBH,EAAS;AAAA,EAC3C,YAAYC,GAAiBC,GAAoB;AAC/C,UAAMD,GAAS,EAAE,GAAGC,GAAQ,OAAO,gBAAgB,GACnD,KAAK,OAAO;AAAA,EAAA;AAEhB;AAKO,MAAME,UAAuBJ,EAAS;AAAA,EAC3C,YAAYC,GAAiBC,GAAoB;AAC/C,UAAMD,GAAS,EAAE,GAAGC,GAAQ,OAAO,gBAAgB,GACnD,KAAK,OAAO;AAAA,EAAA;AAEhB;AAKO,MAAMG,UAAwBL,EAAS;AAAA,EAC5C,YAAYE,GAAoB;AAC9B,UAAM,MAAM,EAAE,GAAGA,GAAQ,OAAO,iBAAiB,GACjD,KAAK,OAAO;AAAA,EAAA;AAEhB;AC1EO,MAAMI,IAAN,MAAMA,UAAiB,MAAM;AAAA,EAKlC,YACErG,IAAoBqG,EAAS,WAC7BJ,GACAK,GACA;AACA,UAAMtG,GAAW;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,GAAGsG;AAAA,IAAA,CACJ,GACD,KAAK,YAAYL,EAAO,WACxB,KAAK,SAASA,EAAO;AAAA,EAAA;AAEzB;AAhBEI,EAAO,YAAY;AAHd,IAAME,IAANF;AAqBA,MAAMG,IAAN,MAAMA,UAA0BD,EAAS;AAAA,EAG9C,YACEN,GACAK,GACA;AACM,UAAAE,EAAkB,WAAWP,GAAQK,CAAI;AAAA,EAAA;AAEnD;AAREE,EAAO,YAAY;AADd,IAAMC,IAAND;AAWA,MAAME,IAAN,MAAMA,UAAsBH,EAAS;AAAA,EAG1C,YACEN,GACAK,GACA;AACM,UAAAI,EAAc,WAAWT,GAAQK,CAAI;AAAA,EAAA;AAE/C;AAREI,EAAO,YAAY;AADd,IAAMC,IAAND;AAWA,MAAME,IAAN,MAAMA,UAAyBL,EAAS;AAAA,EAK7C,YACEN,GAMAK,GACA;AACM,UAAAM,EAAiB,WAAWX,GAAQK,CAAI,GAZjC,KAAA,eAAA,IAab,KAAK,eAAeL,EAAO,cAC3B,KAAK,QAAQA,EAAO;AAAA,EAAA;AAExB;AAjBEW,EAAO,YAAY;AADd,IAAMC,IAAND;ACxCM,MAAAE,IAAW,CAACpF,MACvBA,EAAI;AAAA,EACF;AAAA,EACA,CAACqF,GAAGC,OAASA,IAAM,MAAM,MAAMD,EAAE,YAAY;AAC/C;AAQK,SAASE,EAAcC,GAA0B;AACtD,SAAOC,EAAU;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,KACCD,CAAI;AACT;AAOO,SAASE,IAAa;AAC3B,SAAOD,EAAU;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EAAA,GACC,OAAO,SAAS,QAAQ;AAC7B;AAOO,SAASE,IAAa;AAC3B,SAAOF,EAAU;AAAA,IACf;AAAA,IACA;AAAA,EAAA,GACC,OAAO,SAAS,IAAI;AACzB;AASgB,SAAAA,EAAUG,GAA8BC,GAA8B;AAChF,SAACA,IACED,EAAU,KAAK,CAAQxE,MACxB,OAAOA,KAAS,WACXA,MAASyE,IAEXzE,EAAK,KAAKyE,CAAQ,CAC1B,IANqB;AAOxB;ACzDO,SAASC,EAAcC,GAAyC;AACrE,MAAIA,MAAY;AACd;AAGE,MAAAC;AACE,QAAAC,IAAiB,IAAI,IAAI,uBAAuB;AAElD,MAAA;AACE,QAAA,OAAOF,KAAY;AACrB,WACGA,MAAY,MAAMA,EAAQ,kBAAkB,WAC7CL;AAEU,QAAAM,IAAAC;AAAA,eAIVD,IADED,EAAQ,WAAW,SAAS,KAAKA,EAAQ,WAAW,UAAU,IACxC,IAAI,IAAIA,CAAO,IAAI,QAGvCC,KAAW,CAACT,EAAcS,KAAA,gBAAAA,EAAS,QAAQ;AACvC,cAAA,IAAI,MAAM,8BAA8B;AAAA,UAGpD,CAAWL,QACCK,IAAAC;AAAA,UAEF;AACH,WAAAD;AAAA,EAAA;AAGF,SAAAA;AACT;AAQsB,eAAAE,EACpBC,GACAH,GACkB;AAClB,SAAKA,IAIkB;AAAA,IACrB,IAAI,IAAI,OAAOG,CAAa,gBAAgBH,CAAO;AAAA,IACnD;AAAA,MACE,QAAQ;AAAA,IAAA;AAAA,IAGT,KAAK,MAAM,EAAI,EACf,MAAM,MAAM,EAAK,IAVX;AAaX;;AC9CO,MAAMI,WAA8B,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+ErD,cAAc;AACN,UAAA,GAtEkB,KAAA,OAAA,QAK1B,KAAA,qCAAqB,IAAI;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD,GAoBD,KAAA,YAAY,IAAIvC,EAAc,GAUD,KAAA,KAAA,MAKlB,KAAA,WAAA,IAAI,qBAAqB,CAACwC,MAAY;AAC/C,WAAK,OAAO,MAAM,kCAAkC,EAAE,SAAAA,GAAS,GACvDA,EAAA,QAAQ,CAACC,MAAU;AACpB,aAAA;AAAA,UACH,IAAInB,EAAiB;AAAA,YACnB,WAAW,KAAK;AAAA,YAChB,QAAQ,KAAK;AAAA,YACb,cAAcmB,EAAM;AAAA,YACpB,OAAAA;AAAA,UACD,CAAA;AAAA,QACH;AAAA,MAAA,CACD;AAAA,IAAA,CACF,GA0GD,KAAA,UAAU,IAAI,eAAe,GAyU7B,KAAA,eAAe,MAAM;AV/gBvB,UAAA1C;AUghBI,WAAK,OAAO,MAAM,gBAAgB,EAAE,OAAO,KAAK,IAAI;AAChD,UAAA;AACG,SAAAA,IAAA,KAAA,aAAA,QAAAA,EAAU,KAAK,KAAK;AAAA,eAClBP,GAAG;AACJ,cAAAS,IAAO,KAAK,aAAa,MAAM,GAC/ByC,IAAwB,KAAK,aAAa,SAAS;AACzD,aAAK,OAAO;AAAA,UACV,0DAA0DzC,CAAI,IAAIyC,CAAqB;AAAA,QACzF,GACK,KAAA,OAAO,MAAMlD,CAAC;AAAA,MAAA;AAAA,IAEvB,GAKA,KAAA,kBAAkB,MAAM;AVhiB1B,UAAAO;AUiiBI,WAAK,OAAO,MAAM,mBAAmB,EAAE,OAAO,KAAK,IAAI;AACnD,UAAA;AACF,SAAAA,IAAA,KAAK,aAAL,QAAAA,EAAe;AAAA,eACRP,GAAG;AACJ,cAAAS,IAAO,KAAK,aAAa,MAAM,GAC/ByC,IAAwB,KAAK,aAAa,SAAS;AACzD,aAAK,OAAO;AAAA,UACV,wDAAwDzC,CAAI,IAAIyC,CAAqB;AAAA,QACvF,GACK,KAAA,OAAO,MAAMlD,CAAC;AAAA,MAAA;AAAA,IAEvB,GAKA,KAAA,oBAAoB,MAAM;AVjjB5B,UAAAO,GAAA4C;AUkjBQ,UAAA,SAAS,cAAc,uCAAuC,EAAG;AAE/D,YAAAC,IAAiB,SAAS,cAAc,QAAQ;AACtD,MAAAA,EAAe,OAAO,UACPA,EAAA,aAAa,QAAQ,wBAAwB,GAE5DA,EAAe,cAAc;AAAA,qCACG7C,IAAA,KAAK,YAAL,gBAAAA,EAAc,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,MAKlD,KAAK,GACE,SAAA,KAAK,YAAY6C,CAAc;AAElC,YAAAC,IAAmB,SAAS,cAAc,QAAQ;AACxD,MAAAA,EAAiB,OAAO,UACxBA,EAAiB,MAAM,IAAGF,IAAA,KAAK,YAAL,gBAAAA,EAAc,MAAM,iBACrC,SAAA,KAAK,YAAYE,CAAgB;AAAA,IAC5C,GA/dO,KAAA,SAAS,IAAIjG,EAAO;AAEzB,UAAMkG,IACJ,YAAY,UAAU,eAAe,iBAAiB;AAEpD,QAAA;AACI,YAAAC,IAAYD,KAAuB,KAAK,gBAAgB;AAAA,aACvD,GAAG;AACL,WAAA,OAAO,MAAM,CAAC;AAAA,IAAA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,MAAM,oBAAoB;AVvH5B,QAAA/C;AUwHQ,QAAA;AACI,YAAAE,IAAO,KAAK,aAAa,MAAM,GAC/BG,IAAe,KAAK,aAAa,SAAS;AAChD,WAAK,YAAYJ,EAAc,WAAWC,GAAMG,CAAY,GACvD,KAAA,OAAO,YAAY,KAAK,WAC7B,KAAK,OAAO,YAAY,KAAK,aAAa,KAAK,CAAC,GAC3C,KAAA,OAAO,MAAM,mBAAmB,IACrCL,IAAA,KAAK,OAAL,QAAAA,EAAS,SACJ,KAAA,KAAK,IAAI,gBAAgB,GAC9B,KAAK,MAAM,MAAM,KAAK,KAAK,KAAK,GAAG,MAAM,GACzC,KAAK,MAAM,GACX,KAAK,aAAa;AAAA,aACX,GAAG;AACV,MAAI,aAAa,SACf,sBAAsB,MAAM;AAC1B,aAAK,UAAU,CAAC;AAAA,MAAA,CACjB,GAGH,KAAK,QAAQ,CAAU;AAAA,IAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,UAAUiD,GAAc;AAEtB,QADA,KAAK,OAAO,MAAM,aAAa,EAAE,OAAAA,GAAO,GACpCA,aAAiBxC;AACd,WAAA;AAAA,QACH,IAAI,WAAW,aAAa;AAAA,UAC1B,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAAwC;AAAA,UACA,SAASA,EAAM;AAAA,QAChB,CAAA;AAAA,MACH;AAAA,SACK;AAEL,YAAMC,IAAe,IAAIzC,EAASwC,EAAM,SAAS;AAAA,QAC/C,WAAW,KAAK;AAAA,QAChB,OAAAA;AAAA,MAAA,CACD;AAEI,WAAA;AAAA,QACH,IAAI,WAAW,aAAa;AAAA,UAC1B,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,OAAOC;AAAA,UACP,SAASA,EAAa;AAAA,QACvB,CAAA;AAAA,MACH;AAAA,IAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,uBAAuB;AVxLzB,QAAAlD;AUyLI,KAAAA,IAAA,KAAK,OAAL,QAAAA,EAAS,SACJ,KAAA,OAAO,MAAM,sBAAsB;AAClC,UAAAE,IAAO,KAAK,aAAa,MAAM;AACrC,SAAK,gBAAgB,GACrB,KAAK,OAAO,KAAK,0BAA0BA,CAAI,gBAAgB,GAC/D,KAAK,SAAS,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe3B,UAAUT,GAAS;AACjB,SAAK,OAAO,MAAM,aAAa,EAAE,OAAOA,GAAG;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS7C,UAAUA,GAAU;AAElB,QADA,KAAK,OAAO,MAAM,aAAa,EAAE,OAAOA,GAAG,GACvCA,aAAa,OAAO;AACtB,YAAM0D,IAAc,IAAItC,EAAepB,EAAE,SAAS;AAAA,QAChD,OAAOA;AAAA,QACP,WAAW,KAAK;AAAA,MAAA,CACjB;AACD,4BAAsB,MAAM;AAC1B,aAAK,UAAU0D,CAAW,GAC1B,KAAK,QAAQA,CAAW;AAAA,MAAA,CACzB;AAAA,IAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASF,MAAM,QAAQC,GAAoB;AAC5B,QAAA;AACI,YAAAA,GACN,KAAK,OAAO,MAAM,WAAW,EAAE,KAAAA,GAAK,GAC/B,KAAA;AAAA,QACH,IAAI/B,EAAc;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,QACd,CAAA;AAAA,MACH,GAEA,KAAK,QAAQ,WAAW,QACxB,OAAO,KAAK,QAAQ,UAEf,KAAA,SAAS,QAAQ,IAAI;AAAA,aACnB,GAAG;AAEV,UADA,KAAK,OAAO,MAAM,wBAAwB,EAAE,OAAO,GAAG,GAClD,aAAa,OAAO;AACtB,cAAM8B,IAAc,IAAItC,EAAe,EAAE,SAAS;AAAA,UAChD,OAAO;AAAA,UACP,WAAW,KAAK;AAAA,QAAA,CACjB;AACD,8BAAsB,MAAM;AAC1B,eAAK,UAAUsC,CAAW,GAC1B,KAAK,QAAQA,CAAW;AAAA,QAAA,CACzB;AAAA,MAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQF,YAAY5H,GAAY;AACtB,SAAK,OAAO,MAAM,eAAe,EAAE,OAAAA,GAAO,GACrC,KAAA,QAAQ,MAAM,YAAYA,CAAK;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYtC,MAAM8H,GAAiC;AV5RzC,QAAArD,GAAA4C;AU6RS,SAAA,OAAO,MAAM,SAASS,CAAW;AAClC,QAAA;AAGF,UAFA,KAAK,OACH,KAAK,aAAa,aAAa,KAAK,UAAU,WAAW,QACvD,KAAK,WAAW;AACd,YAAA,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,yBAAyB;AAGrC,cAAAC,IAAM,KAAK,eAAe,MAC1BC,IACJ,KAAK,cAAc,KAAK,aAAa,EAAE,MAAM,KAAK,MAAM;AAqB1D,YAnBK,KAAA;AAAA,UACH,IAAIpC,EAAkB;AAAA,YACpB,WAAW,KAAK;AAAA,YAChB,QAAQ,KAAK;AAAA,UACd,CAAA;AAAA,QACH,GAGE,CAACoC,EAAO,cAAc,yCAAyC,KAC/D,CAACA,EAAO,mBAAmB,WAEtB,OAAO,0BACL,KAAA,OAAO,MAAM,wCAAwC,GACnD,OAAA,wBAAwB,IAAI,cAAc,GAC1C,OAAA,sBAAsB,YAAYC,EAAM,IAE1CD,EAAA,qBAAqB,CAAC,OAAO,qBAAqB,IAGvD,CAACD,GAAK;AACH,eAAA,OAAO,MAAM,oCAAoC;AAChD,gBAAAG,IAAW,SAAS,cAAc,UAAU;AAClD,UAAAA,EAAS,YAAY,gDACrB,KAAK,YAAYA,CAAQ,GACzBF,EAAO,YAAYE,EAAS,QAAQ,UAAU,EAAI,CAAC;AAAA,QAAA;AAGrD,cAAMC,IAAO,KAAK,MAAM,KAAK,aAAa,sBAAsB,CAAE,GAE5DC,IAAa,OAAO;AAAA,UACxB,CAAC,GAAG,KAAK,UAAU,EAChB;AAAA,YACC,CAACtF,MACC,CAAC,KAAK,eAAe,IAAIA,EAAU,IAAI,KACvC,CAACA,EAAU,KAAK,WAAW,OAAO;AAAA,UAAA,EAErC,IAAI,CAACA,MAAc,CAACA,EAAU,MAAMA,EAAU,KAAK,CAAC;AAAA,QACzD;AAGK,aAAA,WAAW,IAAIY,EAAS;AAAA,UAC3B,OAAMe,IAAA,KAAK,cAAL,gBAAAA,EAAgB;AAAA,UACtB,SAAS;AAAA,UACT,UAAU;AAAA,UACV,YAAY,KAAK;AAAA,UACjB,QAAQ,KAAK;AAAA,QAAA,CACd,GAEG,CAAC0D,KAAQ,OAAO,KAAKC,CAAU,EAAE,SAAS,MAC5C,KAAK,OAAO;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,QACF,GACA,KAAK,OAAO;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAGF,cAAM,EAAE,WAAAC,GAAW,OAAAC,IAAQ,QAAQ,QAAQ,EAAA,IACzC,KAAK;AAAA,UACHN;AAAA,UACA;AAAA,YACE,GAAIG,KAAQC;AAAA,YACZ,KAAK,KAAK;AAAA,YACV,MAAMD,KAAQC;AAAA,YACd,MAAM,KAAK,QAAQ;AAAA,YACnB,UAAU,KAAK;AAAA,YACf,aAAa,CAAC,CAACN;AAAA,YACf,UAAU,KAAK;AAAA,UACjB;AAAA,UACAC;AAAA,UACA,KAAK,UAAU,KAAK,IAAI;AAAA,QAAA,KACrB,CAAC;AAEJ,QAAAM,WAAgB,YAAYA,IAEhC,KAAK,QAAQC,CAAK;AAAA,MAAA;AAAA,aAEbC,GAAK;AACZ,iBAAK,OAAO;AAAA,QACV,6DAA4DlB,IAAA,KAAK,cAAL,gBAAAA,EAAgB,UAAU;AAAA,MACxF,GACK,KAAA,OAAO,MAAMkB,CAAG,GAEfA;AAAA,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUF,QAAQrE,GAAU;AV5YpB,QAAAO;AU6YI,SAAK,OAAO,MAAM,WAAW,EAAE,OAAOP,GAAG;AAEzC,UAAMgE,IACJ,KAAK;AAAA,MACH;AAAA,IAAA,KACG,KAAK,cAAmC,UAAU;AAEzD,IAAIA,MACG,KAAA,OAAO,MAAM,4CAA4C,IAC9DzD,IAAA,KAAK,eAAL,QAAAA,EAAiB,gBAAgByD,EAAS,QAAQ,UAAU,EAAI,KAG7D,KAAK,QAAQ,aACX,KAAA,QAAQ,WAAWjC,EAAS/B,EAAE,KAAK,QAAQ,OAAO,EAAE,CAAC,IAE5D,OAAO,KAAK,QAAQ,UAEpB,KAAK,SAAS,WAAW;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3B,MAAM,KAAKsE,GAAqB;AVtalC,QAAA/D;AUyaQ,QAFC,KAAA,OAAO,MAAM,MAAM,GAEpB,CAAC,KAAK,UAAU;AACZ,YAAA,IAAI,MAAM,eAAe;AAG3B,UAAAE,IAAO,KAAK,aAAa,MAAM,GAC/ByC,IAAwB,KAAK,aAAa,SAAS,GACnDqB,IAAU,OAAO,KAAK,aAAa,cAAc,KAAK,GAAK,GAC3D7B,IAAU,KAAK,aAAa,UAAU;AACvC,SAAA,UAAUD,EAAcC,CAAO;AACpC,UAAM8B,IAAY,MAAM3B;AAAA,MACtB,KAAK,UAAU;AAAA,MACf,KAAK;AAAA,IACP,GAGMpG,IAAK,KAAK,aAAa,IAAI;AAE7B,IAAA+H,KAAa,KAAK,YACf,KAAA,OAAO,MAAM,0BAA0B,GAC5C,KAAK,kBAAkB,IAGzB,KAAK,SAASA,IACV,IAAGjE,IAAA,KAAK,YAAL,gBAAAA,EAAc,MAAM,QAAQ,KAAK,UAAU,IAAI,iBAAiB9D,CAAE,KACrE,kCAAkC,KAAK,UAAU,GAAG,IAAI,KAAK,UAAU,IAAI,GACzEyG,IAAwB,IAAIA,CAAqB,KAAK,SACxD,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,UAAU,IAAI,UAAUzG,CAAE;AAE1D,QAAA;AACF,aAAO,MAAM,IAAI;AAAA,QACf,CAACgI,GAASC,MAAW;AACnB,UAAAJ,EAAO,eAAe;AAChB,gBAAAK,IAAK,WAAW,MAAM;AACrB,iBAAA,OAAO,MAAM,0BAA0B,GAC5CD;AAAA,cACE,IAAIrD,EAAgB;AAAA,gBAClB,WAAW,KAAK;AAAA,gBAChB,QAAQ,KAAK;AAAA,cACd,CAAA;AAAA,YACH;AAAA,UAAA,GACC,OAAOkD,CAAO,CAAC;AAElB,cAAI,KAAK;AACP;AAAA;AAAA,cAAiC,KAAK;AAAA;AAAA,cACnC,KAAK,CAAC,EAAE,SAASK,QAA8B;AAC9C,kBAAIA;AACF,6BAAaD,CAAE,GACfF,EAAQG,CAAuB;AAAA;AAE/B,sBAAM,IAAIzD;AAAA,kBACR;AAAA,kBACA;AAAA,oBACE,WAAW,KAAK;AAAA,oBAChB,QAAQ,KAAK;AAAA,kBAAA;AAAA,gBAEjB;AAAA,YAAA,CACH,EACA,MAAM,CAACnB,MAAM;AACZ,2BAAa2E,CAAE,GACV,KAAA,OAAO,MAAM3E,CAAC,GACfA,aAAa,SAAS,EAAEA,aAAamB,KACvCuD;AAAA,gBACE,IAAIvD,EAAenB,EAAE,SAAS;AAAA,kBAC5B,WAAW,KAAK;AAAA,kBAChB,QAAQ,KAAK;AAAA,gBACd,CAAA;AAAA,cACH,IAEA0E,EAAO1E,CAAC;AAAA,YACV,CACD;AAAA;AAEH,+BAAa2E,CAAE,GACT,IAAIxD,EAAe,mBAAmBV,CAAI,IAAI;AAAA,cAClD,WAAW,KAAK;AAAA,cAChB,QAAQ,KAAK;AAAA,YAAA,CACd;AAGI,UAAA6D,EAAA;AAAA,YACL;AAAA,YACA,MAAM;AAGJ,cAAAI,EAAOJ,EAAO,MAAM;AAAA,YACtB;AAAA,YACA,EAAE,MAAM,GAAK;AAAA,UACf;AAAA,QAAA;AAAA,MAEJ;AAAA,aACOD,GAAK;AACZ,iBAAK,OAAO;AAAA,QACV,oDAAoD5D,CAAI,IAAIyC,CAAqB;AAAA,MACnF,GAEMmB;AAAA,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsEF,yBAAyBrF,GAAc6F,GAAkBC,GAAkB;AAOzE,YANK,KAAA,OAAO,MAAM,6CAA6C;AAAA,MAC7D,MAAA9F;AAAA,MACA,UAAA6F;AAAA,MACA,UAAAC;AAAA,IAAA,CACD,GAEO9F,GAAM;AAAA,MACZ,KAAK;AACE,aAAA,OAAO,YAAY8F,CAAQ;AAAA,IAClC;AAAA,EACF;AAEJ;","x_google_ignoreList":[0,1]}
|
package/package.json
CHANGED
|
@@ -346,14 +346,14 @@ export class FTCustomCodeComponent extends HTMLElement {
|
|
|
346
346
|
|
|
347
347
|
if (!data && Object.keys(extraProps).length > 0) {
|
|
348
348
|
this.logger.warn(
|
|
349
|
-
|
|
349
|
+
"passing component settings as webcomponent attributes is %cDEPRECATED%c and will be removed in v3.",
|
|
350
350
|
"font-weight: bold",
|
|
351
|
-
"
|
|
351
|
+
"",
|
|
352
352
|
);
|
|
353
353
|
this.logger.warn(
|
|
354
|
-
|
|
354
|
+
"Please use the %cdata-component-props%c attribute instead.",
|
|
355
355
|
"text-decoration: underline;",
|
|
356
|
-
"
|
|
356
|
+
"",
|
|
357
357
|
);
|
|
358
358
|
}
|
|
359
359
|
|
package/src/logger.ts
CHANGED
|
@@ -55,9 +55,25 @@ export class Logger {
|
|
|
55
55
|
this.component = component;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
private formatConsoleArgs(args: any[]) {
|
|
59
|
+
const suffix = this.component ? [this.component] : [];
|
|
60
|
+
|
|
61
|
+
if (args.length === 0) {
|
|
62
|
+
return [LOG_PREFIX, ...suffix];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const [first, ...rest] = args;
|
|
66
|
+
|
|
67
|
+
if (typeof first === "string") {
|
|
68
|
+
return [`${LOG_PREFIX} ${first}`, ...rest, ...suffix];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return [LOG_PREFIX, first, ...rest, ...suffix];
|
|
72
|
+
}
|
|
73
|
+
|
|
58
74
|
debug(...args: any[]) {
|
|
59
75
|
if (this.level <= LogLevel.DEBUG) {
|
|
60
|
-
console.info(
|
|
76
|
+
console.info(...this.formatConsoleArgs(args));
|
|
61
77
|
}
|
|
62
78
|
}
|
|
63
79
|
|
|
@@ -65,19 +81,19 @@ export class Logger {
|
|
|
65
81
|
|
|
66
82
|
info(...args: any[]) {
|
|
67
83
|
if (this.level <= LogLevel.INFO) {
|
|
68
|
-
console.info(
|
|
84
|
+
console.info(...this.formatConsoleArgs(args));
|
|
69
85
|
}
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
warn(...args: any[]) {
|
|
73
89
|
if (this.level <= LogLevel.WARN) {
|
|
74
|
-
console.warn(
|
|
90
|
+
console.warn(...this.formatConsoleArgs(args));
|
|
75
91
|
}
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
error(...args: any[]) {
|
|
79
95
|
if (this.level <= LogLevel.ERROR) {
|
|
80
|
-
console.error(
|
|
96
|
+
console.error(...this.formatConsoleArgs(args));
|
|
81
97
|
}
|
|
82
98
|
}
|
|
83
99
|
|