@financial-times/custom-code-component 1.11.1 → 2.0.1-alpha.10

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.
Files changed (35) hide show
  1. package/dist/index.js +598 -0
  2. package/dist/index.js.map +1 -0
  3. package/dist/webcomponent/src/custom-code-component.d.ts +55 -0
  4. package/dist/webcomponent/src/environment.d.ts +15 -0
  5. package/dist/webcomponent/src/errors.d.ts +27 -0
  6. package/dist/webcomponent/src/events.d.ts +10 -0
  7. package/dist/webcomponent/src/get-trace.d.ts +8 -0
  8. package/dist/webcomponent/src/index.d.ts +1 -0
  9. package/dist/webcomponent/src/logger.d.ts +20 -0
  10. package/dist/webcomponent/src/path.d.ts +23 -0
  11. package/dist/{tracking.d.ts → webcomponent/src/tracking.d.ts} +12 -4
  12. package/dist/webcomponent/src/util.d.ts +33 -0
  13. package/dist/webcomponent/test/environment.test.d.ts +1 -0
  14. package/dist/webcomponent/test/error-handling.test.d.ts +8 -0
  15. package/dist/webcomponent/test/example.d.ts +11 -0
  16. package/dist/webcomponent/test/generate-readable-stream.d.ts +8 -0
  17. package/dist/webcomponent/test/path.test.d.ts +5 -0
  18. package/dist/webcomponent/test/ssr.test.d.ts +4 -0
  19. package/dist/webcomponent/test/utils.test.d.ts +1 -0
  20. package/dist/webcomponent/vite.config.d.ts +2 -0
  21. package/dist/webcomponent/vitest.config.d.ts +2 -0
  22. package/package.json +25 -17
  23. package/src/custom-code-component.ts +247 -167
  24. package/src/environment.ts +77 -0
  25. package/src/errors.ts +73 -0
  26. package/src/events.ts +22 -0
  27. package/src/{get-trace.js → get-trace.ts} +23 -14
  28. package/src/index.ts +8 -0
  29. package/src/logger.ts +71 -0
  30. package/src/path.ts +83 -0
  31. package/src/tracking.ts +20 -11
  32. package/src/util.ts +66 -0
  33. package/dist/custom-code-component.d.ts +0 -21
  34. package/dist/custom-code-component.js +0 -380
  35. package/src/custom-code-component.xsd +0 -67
package/dist/index.js ADDED
@@ -0,0 +1,598 @@
1
+ function l(o) {
2
+ this.listenerMap = [{}, {}], o && this.root(o), this.handle = l.prototype.handle.bind(this), this._removedListeners = [];
3
+ }
4
+ l.prototype.root = function(o) {
5
+ const t = this.listenerMap;
6
+ let e;
7
+ if (this.rootElement) {
8
+ for (e in t[1])
9
+ t[1].hasOwnProperty(e) && this.rootElement.removeEventListener(e, this.handle, !0);
10
+ for (e in t[0])
11
+ t[0].hasOwnProperty(e) && this.rootElement.removeEventListener(e, this.handle, !1);
12
+ }
13
+ if (!o || !o.addEventListener)
14
+ return this.rootElement && delete this.rootElement, this;
15
+ this.rootElement = o;
16
+ for (e in t[1])
17
+ t[1].hasOwnProperty(e) && this.rootElement.addEventListener(e, this.handle, !0);
18
+ for (e in t[0])
19
+ t[0].hasOwnProperty(e) && this.rootElement.addEventListener(e, this.handle, !1);
20
+ return this;
21
+ };
22
+ l.prototype.captureForType = function(o) {
23
+ return ["blur", "error", "focus", "load", "resize", "scroll"].indexOf(o) !== -1;
24
+ };
25
+ l.prototype.on = function(o, t, e, n) {
26
+ let s, r, i, c;
27
+ if (!o)
28
+ throw new TypeError("Invalid event type: " + o);
29
+ if (typeof t == "function" && (n = e, e = t, t = null), n === void 0 && (n = this.captureForType(o)), typeof e != "function")
30
+ throw new TypeError("Handler must be a type of Function");
31
+ return s = this.rootElement, r = this.listenerMap[n ? 1 : 0], r[o] || (s && s.addEventListener(o, this.handle, n), r[o] = []), t ? /^[a-z]+$/i.test(t) ? (c = t, i = T) : /^#[a-z0-9\-_]+$/i.test(t) ? (c = t.slice(1), i = S) : (c = t, i = Element.prototype.matches) : (c = null, i = $.bind(this)), r[o].push({
32
+ selector: t,
33
+ handler: e,
34
+ matcher: i,
35
+ matcherParam: c
36
+ }), this;
37
+ };
38
+ l.prototype.off = function(o, t, e, n) {
39
+ let s, r, i, c, h;
40
+ if (typeof t == "function" && (n = e, e = t, t = null), n === void 0)
41
+ return this.off(o, t, e, !0), this.off(o, t, e, !1), this;
42
+ if (i = this.listenerMap[n ? 1 : 0], !o) {
43
+ for (h in i)
44
+ i.hasOwnProperty(h) && this.off(h, t, e);
45
+ return this;
46
+ }
47
+ if (c = i[o], !c || !c.length)
48
+ return this;
49
+ for (s = c.length - 1; s >= 0; s--)
50
+ r = c[s], (!t || t === r.selector) && (!e || e === r.handler) && (this._removedListeners.push(r), c.splice(s, 1));
51
+ return c.length || (delete i[o], this.rootElement && this.rootElement.removeEventListener(o, this.handle, n)), this;
52
+ };
53
+ l.prototype.handle = function(o) {
54
+ let t, e;
55
+ const n = o.type;
56
+ let s, r, i, c, h = [], a;
57
+ const m = "ftLabsDelegateIgnore";
58
+ if (o[m] === !0)
59
+ return;
60
+ switch (a = o.target, a.nodeType === 3 && (a = a.parentNode), a.correspondingUseElement && (a = a.correspondingUseElement), s = this.rootElement, r = o.eventPhase || (o.target !== o.currentTarget ? 3 : 2), r) {
61
+ case 1:
62
+ h = this.listenerMap[1][n];
63
+ break;
64
+ case 2:
65
+ this.listenerMap[0] && this.listenerMap[0][n] && (h = h.concat(this.listenerMap[0][n])), this.listenerMap[1] && this.listenerMap[1][n] && (h = h.concat(this.listenerMap[1][n]));
66
+ break;
67
+ case 3:
68
+ h = this.listenerMap[0][n];
69
+ break;
70
+ }
71
+ let u = [];
72
+ for (e = h.length; a && e; ) {
73
+ for (t = 0; t < e && (i = h[t], !!i); t++)
74
+ a.tagName && ["button", "input", "select", "textarea"].indexOf(a.tagName.toLowerCase()) > -1 && a.hasAttribute("disabled") ? u = [] : i.matcher.call(a, i.matcherParam, a) && u.push([o, a, i]);
75
+ if (a === s || (e = h.length, a = a.parentElement || a.parentNode, a instanceof HTMLDocument))
76
+ break;
77
+ }
78
+ let b;
79
+ for (t = 0; t < u.length; t++)
80
+ if (!(this._removedListeners.indexOf(u[t][2]) > -1) && (c = this.fire.apply(this, u[t]), c === !1)) {
81
+ u[t][0][m] = !0, u[t][0].preventDefault(), b = !1;
82
+ break;
83
+ }
84
+ return b;
85
+ };
86
+ l.prototype.fire = function(o, t, e) {
87
+ return e.handler.call(t, o, t);
88
+ };
89
+ function T(o, t) {
90
+ return o.toLowerCase() === t.tagName.toLowerCase();
91
+ }
92
+ function $(o, t) {
93
+ return this.rootElement === window ? (
94
+ // Match the outer document (dispatched from document)
95
+ t === document || // The <html> element (dispatched from document.body or document.documentElement)
96
+ t === document.documentElement || // Or the window itself (dispatched from window)
97
+ t === window
98
+ ) : this.rootElement === t;
99
+ }
100
+ function S(o, t) {
101
+ return o === t.id;
102
+ }
103
+ l.prototype.destroy = function() {
104
+ this.off(), this.root();
105
+ };
106
+ function y(o) {
107
+ return typeof o == "string" ? o.trim() : o;
108
+ }
109
+ function v(o, t) {
110
+ for (const e in o)
111
+ t[e] ? console.warn(`You can't set a custom property called ${e}`) : t[e] = o[e];
112
+ }
113
+ const p = Object.freeze({
114
+ DEBUG: 0,
115
+ INFO: 1,
116
+ WARN: 2,
117
+ ERROR: 3,
118
+ TEST: 4,
119
+ DEFAULT: 2
120
+ });
121
+ function N(o) {
122
+ const t = o == null ? void 0 : o.toLowerCase();
123
+ return t === "debug" ? p.DEBUG : t === "info" ? p.INFO : t === "warn" ? p.WARN : t === "error" ? p.ERROR : t === "test" ? p.TEST : p.DEFAULT;
124
+ }
125
+ class C {
126
+ constructor({ level: t = p.DEFAULT } = {
127
+ level: p.DEFAULT
128
+ }) {
129
+ this.log = this.debug, this.level = t;
130
+ }
131
+ debug(...t) {
132
+ this.level <= p.DEBUG && console.info(...t);
133
+ }
134
+ info(...t) {
135
+ this.level <= p.INFO && console.info(...t);
136
+ }
137
+ warn(...t) {
138
+ this.level <= p.WARN && console.warn(...t);
139
+ }
140
+ error(...t) {
141
+ this.level <= p.ERROR && console.error(...t);
142
+ }
143
+ }
144
+ const L = (o, t, e) => {
145
+ const n = Array.from((o == null ? void 0 : o.querySelectorAll(e)) ?? []), s = n.findIndex((r) => r === t);
146
+ if (s !== -1)
147
+ return {
148
+ siblings: n.length,
149
+ position: s
150
+ };
151
+ }, k = [
152
+ "nodeName",
153
+ "className",
154
+ "id",
155
+ "href",
156
+ "text",
157
+ "role"
158
+ ], O = (o) => {
159
+ const t = {};
160
+ for (const e of k) {
161
+ const n = o[e] || o.getAttribute(e) || o.hasAttribute(e);
162
+ n !== void 0 && (typeof n == "boolean" ? t[e] = n : t[e] = y(n));
163
+ }
164
+ return t;
165
+ }, P = (o) => {
166
+ try {
167
+ const t = JSON.parse(o), e = Object.prototype.toString.call(t);
168
+ return [e === "[object Object]" || e === "[object Array]", t];
169
+ } catch {
170
+ return [!1, null];
171
+ }
172
+ }, x = (o) => {
173
+ const [t, e] = P(o);
174
+ return t ? e : o;
175
+ }, I = (o, t) => (o.filter(
176
+ (e) => e.name.match(/^data-trackable|^data-o-|^aria-/i)
177
+ ).forEach((e) => {
178
+ t[e.name] = e.value;
179
+ }), t), M = (o, t, e) => {
180
+ const n = {};
181
+ return e && k.forEach((s) => {
182
+ typeof t[s] < "u" && s !== "id" && (n[s] = t[s]);
183
+ }), o.filter((s) => s.name.match(/^data-trackable-context-/i)).forEach((s) => {
184
+ n[s.name.replace("data-trackable-context-", "")] = x(s.value);
185
+ }), n;
186
+ };
187
+ function D(o, t) {
188
+ const e = o, n = e != null && e.getAttribute("data-trackable") ? `[data-trackable="${e.getAttribute("data-trackable")}"]` : e == null ? void 0 : e.nodeName, s = [], r = {};
189
+ for (; o && o !== t; ) {
190
+ const i = O(o), c = Array.from(o.attributes);
191
+ let h = I(c, i);
192
+ h["data-trackable"] && (h = Object.assign(
193
+ h,
194
+ L(o, e, n)
195
+ )), s.push(h);
196
+ const a = M(c, i, o === e);
197
+ v(a, r), o = o.parentNode;
198
+ }
199
+ return { trace: s, customContext: r };
200
+ }
201
+ const U = ["ctrlKey", "altKey", "shiftKey", "metaKey"];
202
+ class F {
203
+ constructor({
204
+ id: t = "00000000-0000-0000-0000-000000000000",
205
+ name: e = "ccc-component",
206
+ subtype: n = "interactive",
207
+ teamName: s = "djd",
208
+ shadowRoot: r = null,
209
+ category: i = "cta",
210
+ elements: c = 'a, button, input, [role="button"]',
211
+ logger: h
212
+ }) {
213
+ this.cccId = t, this.cccName = e, this.subtype = n, this.teamName = s, this.shadowRoot = r, this.category = i, this.elements = c, this.isInitialised = !1, this.log = h ?? new C();
214
+ }
215
+ // Get properties for the event (as opposed to properties of the clicked element)
216
+ getEventProperties(t) {
217
+ const e = {};
218
+ for (const n of U)
219
+ if (t[n])
220
+ try {
221
+ e[n] = y(t[n]);
222
+ } catch (s) {
223
+ this.log.info(s);
224
+ }
225
+ return e;
226
+ }
227
+ // Controller for handling click events
228
+ handleClickEvent(t, e) {
229
+ return (n, s) => {
230
+ const r = this.getEventProperties(n), { trace: i, customContext: c } = D(s, e);
231
+ r.custom = s.dataset && s.dataset.custom ? JSON.parse(s.dataset.custom) : null, r.domPathTokens = i, r.component = {
232
+ id: this.cccId,
233
+ name: this.cccName,
234
+ type: "custom-code-component",
235
+ subtype: this.subtype
236
+ }, r.teamName = this.teamName, r.url = document.URL, v(c, r), r.method = "ftCustomAnalytics", t = { ...t, ...r }, document.body.dispatchEvent(
237
+ new CustomEvent("oTracking.event", {
238
+ detail: t,
239
+ bubbles: !0,
240
+ composed: !0
241
+ })
242
+ );
243
+ };
244
+ }
245
+ sendSpoorEvent(t, e) {
246
+ const n = {
247
+ category: "component",
248
+ action: "act",
249
+ component: {
250
+ id: this.cccId,
251
+ name: this.cccName,
252
+ type: "custom-code-component",
253
+ subtype: this.subtype
254
+ },
255
+ teamName: this.teamName,
256
+ trigger_action: t,
257
+ custom: e,
258
+ method: "ftCustomAnalytics"
259
+ };
260
+ document.body.dispatchEvent(
261
+ new CustomEvent("oTracking.event", {
262
+ detail: n,
263
+ bubbles: !0,
264
+ composed: !0
265
+ })
266
+ );
267
+ }
268
+ init(t) {
269
+ var e;
270
+ if (!this.isInitialised) {
271
+ this.isInitialised = !0, this.cccId = t || this.cccId;
272
+ const n = {
273
+ action: "click",
274
+ category: this.category
275
+ }, s = (e = this.shadowRoot) == null ? void 0 : e.querySelector("[data-component-root]");
276
+ s && new l(s).on(
277
+ "click",
278
+ this.elements,
279
+ this.handleClickEvent(n, s),
280
+ !0
281
+ );
282
+ }
283
+ }
284
+ }
285
+ class f {
286
+ constructor(t) {
287
+ const { org: e, repo: n, component: s, versionRange: r } = w(
288
+ t
289
+ ) ? t : f.fromString(t);
290
+ this.org = e, this.repo = n, this.component = s, this.versionRange = r;
291
+ }
292
+ set path(t) {
293
+ const { org: e, repo: n, component: s, versionRange: r } = w(
294
+ t
295
+ ) ? t : f.fromString(t);
296
+ this.org = e, this.repo = n, this.component = s, this.versionRange = r;
297
+ }
298
+ get path() {
299
+ return `${this.org}/${this.repo}@${this.versionRange}/${this.component}`;
300
+ }
301
+ toString() {
302
+ return this.path;
303
+ }
304
+ static fromString(t, e) {
305
+ var c;
306
+ if (!t)
307
+ throw new d("No path specified");
308
+ const n = e ?? ((c = t.match(/@[^\/]+/)) == null ? void 0 : c.toString().replace("@", "")) ?? "unknown";
309
+ if (!n)
310
+ throw new d("No version specified");
311
+ const [s, r, i] = t.replace(/@[^\/]+/, "").split("/").reverse();
312
+ return new f({ org: i, repo: r, component: s, versionRange: n });
313
+ }
314
+ }
315
+ function w(o) {
316
+ return typeof o == "object" && o !== null ? "org" in o && "repo" in o && "component" in o : !1;
317
+ }
318
+ class d extends Error {
319
+ constructor(t, e) {
320
+ var n = (...s) => {
321
+ super(...s);
322
+ };
323
+ !e && t ? (n(t), this.component = null) : typeof (e == null ? void 0 : e.component) == "string" ? (n(
324
+ t ?? `${e.cause ?? "Unknown error"} in ${e.component} imported from ${e.source ?? "an undefined source"}.`
325
+ ), this.component = f.fromString(e.component)) : w(e == null ? void 0 : e.component) ? (n(
326
+ t ?? `${e.cause ?? "Unknown error"} in ${e.component.org}/${e.component.repo}/${e.component.component}@${e.component.versionRange} imported from ${e.source ?? "an undefined source"}.`
327
+ ), this.component = new f(e.component)) : (n(
328
+ `${(e == null ? void 0 : e.cause) ?? "Unknown error"} in unknown component imported from ${(e == null ? void 0 : e.source) ?? "unknown source"}.`
329
+ ), this.component = null), this.source = e == null ? void 0 : e.source, Error.captureStackTrace && Error.captureStackTrace(this, d), this.name = "CCCError";
330
+ }
331
+ }
332
+ class g extends d {
333
+ constructor(t, e) {
334
+ super(t, { ...e, cause: "Import error" }), this.name = "CCCImportError";
335
+ }
336
+ }
337
+ class W extends d {
338
+ constructor(t) {
339
+ super(null, { ...t, cause: "Timeout error" }), this.name = "CCCTimeoutError";
340
+ }
341
+ }
342
+ const R = class A extends Event {
343
+ constructor(t, e) {
344
+ super(A.eventType, {
345
+ bubbles: !0,
346
+ cancelable: !1,
347
+ composed: !0,
348
+ ...e
349
+ }), this.component = t.component, this.source = t.source;
350
+ }
351
+ };
352
+ R.eventType = "ccc:ConnectedEvent";
353
+ let j = R;
354
+ const _ = (o) => o.replace(
355
+ /[A-Z]+(?![a-z])|[A-Z]/g,
356
+ (t, e) => (e ? "-" : "") + t.toLowerCase()
357
+ );
358
+ function V(o) {
359
+ return E([
360
+ "localhost",
361
+ "local.ft.com",
362
+ /^.*\.apps\.in\.ft\.com$/
363
+ ], o);
364
+ }
365
+ function z() {
366
+ return E([
367
+ "localhost",
368
+ "local.ft.com",
369
+ /^.*\.in\.ft\.com$/
370
+ ], window.location.hostname);
371
+ }
372
+ function J() {
373
+ return E([
374
+ "spark.ft.com",
375
+ "spark-staging.ft.com"
376
+ ], window.location.host);
377
+ }
378
+ function E(o, t) {
379
+ return t ? o.some((e) => typeof e == "string" ? e === t : e.test(t)) : !1;
380
+ }
381
+ function H(o) {
382
+ if (o === null)
383
+ return;
384
+ let t;
385
+ const e = new URL("http://localhost:5173");
386
+ try {
387
+ if (typeof o == "string") {
388
+ if ((o === "" || o.toLowerCase() === "true") && z())
389
+ t = e;
390
+ else if (t = o.startsWith("http://") || o.startsWith("https://") ? new URL(o) : void 0, t && !V(t == null ? void 0 : t.hostname))
391
+ throw new Error("Unsafe testing host override");
392
+ } else
393
+ J() && (t = e);
394
+ } catch {
395
+ return t;
396
+ }
397
+ return t;
398
+ }
399
+ async function K(o) {
400
+ if (!o)
401
+ return !1;
402
+ function t(n) {
403
+ try {
404
+ return new Promise((s) => {
405
+ const r = new WebSocket(`ws://${n}`, "vite-hmr"), i = setTimeout(() => {
406
+ s(r.readyState === WebSocket.OPEN), r.close();
407
+ }, 50);
408
+ r.addEventListener("error", () => {
409
+ clearTimeout(i), r.close(), s(!1);
410
+ }, { once: !0 });
411
+ });
412
+ } catch {
413
+ return Promise.resolve(!1);
414
+ }
415
+ }
416
+ return await t(o == null ? void 0 : o.host);
417
+ }
418
+ class q extends HTMLElement {
419
+ constructor() {
420
+ super(), this.mode = "open", this.RESERVED_ATTRS = /* @__PURE__ */ new Set([
421
+ "iframe",
422
+ "path",
423
+ "version",
424
+ "data-component-props",
425
+ "data-asset-type",
426
+ "shadow-open",
427
+ "env",
428
+ "load-timeout"
429
+ ]), this.channel = new MessageChannel(), this.initTracking = async () => {
430
+ var e;
431
+ try {
432
+ (e = this.tracking) == null || e.init(this.id);
433
+ } catch (n) {
434
+ const s = this.getAttribute("path"), r = this.getAttribute("version");
435
+ this.log.info(
436
+ `Error initialising tracking on <custom-code-component> ${s}@${r}`
437
+ ), this.log.error(n);
438
+ }
439
+ }, this.log = new C({
440
+ level: N(this.getAttribute("log"))
441
+ });
442
+ const t = HTMLElement.prototype.hasOwnProperty("attachInternals");
443
+ try {
444
+ const e = t && this.attachInternals();
445
+ } catch (e) {
446
+ this.log.error(e);
447
+ }
448
+ }
449
+ async connectedCallback() {
450
+ try {
451
+ const t = this.getAttribute("path"), e = this.getAttribute("version");
452
+ this.component = f.fromString(t, e), this.lightRoot = Array.from(this.childNodes), this.app = await this.load(), await this.mount(), await this.initTracking();
453
+ } catch (t) {
454
+ t instanceof Error && requestAnimationFrame(() => {
455
+ this.emitError(t);
456
+ }), this.unmount(t);
457
+ }
458
+ }
459
+ emitError(t) {
460
+ var n;
461
+ let e;
462
+ if (t instanceof d && ((n = t.name) != null && n.startsWith("CCC")) ? e = t.name.replace(/^CCC/, "ccc:") : e = `ccc:${(t == null ? void 0 : t.name) ?? "UnknownError"}`, !e)
463
+ return this.log.debug(t);
464
+ this.dispatchEvent(
465
+ new ErrorEvent(e, {
466
+ bubbles: !0,
467
+ cancelable: !1,
468
+ composed: !0,
469
+ error: t,
470
+ message: t.message
471
+ })
472
+ );
473
+ }
474
+ disconnectedCallback() {
475
+ const t = this.getAttribute("path");
476
+ this.log.info(`<custom-code-component:${t}> disconnected`), typeof this.onunmount == "function" && this.onunmount();
477
+ }
478
+ onmessage() {
479
+ }
480
+ onunmount(t) {
481
+ }
482
+ async onready(t) {
483
+ try {
484
+ await t;
485
+ } catch (e) {
486
+ e instanceof Error && this.emitError(e);
487
+ }
488
+ }
489
+ postMessage(t) {
490
+ this.channel.port1.postMessage(t);
491
+ }
492
+ async mount(t) {
493
+ var e, n;
494
+ try {
495
+ if (this.mode = this.getAttribute("shadow-open") == "false" ? "closed" : "open", this.component) {
496
+ if (this.dispatchEvent(
497
+ new j({
498
+ component: this.component,
499
+ source: this.source
500
+ })
501
+ ), this.dataset.cccReady = "true", delete this.dataset.cccError, !this.app)
502
+ throw new Error("CCC mounted without App");
503
+ const s = this.shadowRoot !== null, r = this.shadowRoot ?? this.attachShadow({ mode: this.mode }), i = JSON.parse(this.getAttribute("data-component-props")), c = Object.fromEntries(
504
+ [...this.attributes].filter((u) => !this.RESERVED_ATTRS.has(u.name)).map((u) => [u.name, u.value])
505
+ );
506
+ this.tracking = new F({
507
+ name: (e = this.component) == null ? void 0 : e.toString(),
508
+ subtype: "interactive",
509
+ teamName: "djd",
510
+ shadowRoot: this.shadowRoot,
511
+ logger: this.log
512
+ });
513
+ const { unmount: h, onmessage: a, ready: m } = this.app(
514
+ r,
515
+ {
516
+ ...c,
517
+ data: i,
518
+ port: this.channel.port2,
519
+ tracking: this.tracking,
520
+ prerendered: !!t,
521
+ children: this.children
522
+ },
523
+ s
524
+ ) || {};
525
+ h && (this.onunmount = h), a && (this.onmessage = a), m && this.onready(m);
526
+ }
527
+ } catch (s) {
528
+ throw this.log.info(
529
+ `<custom-code-component> uncaught error during mount from ${(n = this.component) == null ? void 0 : n.toString()}`
530
+ ), this.log.error(s), s;
531
+ }
532
+ }
533
+ // Called in top-level error handler
534
+ // Replace shadow root with light DOM children on error
535
+ unmount(t) {
536
+ var e;
537
+ this.lightRoot && (this.onunmount(), (e = this.shadowRoot) == null || e.replaceChildren(...this.lightRoot), this.dataset.cccError || (this.dataset.cccError = _(t.name.replace("CCC", ""))), delete this.dataset.cccReady);
538
+ }
539
+ async load() {
540
+ if (!this.component)
541
+ throw new Error("No path found");
542
+ const t = this.getAttribute("path"), e = this.getAttribute("version"), n = Number(this.getAttribute("load-timeout") || 1e4), s = this.getAttribute("testEnv"), r = H(s), i = await K(r), c = this.getAttribute("id");
543
+ this.source = i ? `${r == null ? void 0 : r.origin}/src/${this.component.component}/index.jsx?id=${c}` : `https://www.ft.com/__component/${this.component.org}/${this.component.repo}${e ? `@${e}` : "@latest"}/${this.component.component}/${this.component.component}.js?id=${c}`;
544
+ try {
545
+ return await new Promise(
546
+ (h, a) => {
547
+ const m = setTimeout(() => {
548
+ this.log.error("CCC import timeout error"), a(
549
+ new W({
550
+ component: this.component,
551
+ source: this.source
552
+ })
553
+ );
554
+ }, Number(n));
555
+ if (this.source)
556
+ import(
557
+ /* webpackIgnore: true */
558
+ this.source
559
+ /* @vite-ignore */
560
+ ).then(({ default: u }) => {
561
+ if (u)
562
+ clearTimeout(m), h(u);
563
+ else
564
+ throw new g(
565
+ "No component renderer default export found",
566
+ {
567
+ component: this.component,
568
+ source: this.source
569
+ }
570
+ );
571
+ }).catch((u) => {
572
+ clearTimeout(m), this.log.error(u), u instanceof Error && !(u instanceof g) ? a(
573
+ new g(u.message, {
574
+ component: this.component,
575
+ source: this.source
576
+ })
577
+ ) : a(u);
578
+ });
579
+ else
580
+ throw clearTimeout(m), new g(`Unable to mount ${t}`, {
581
+ component: this.component,
582
+ source: this.source
583
+ });
584
+ }
585
+ );
586
+ } catch (h) {
587
+ throw this.log.error(
588
+ `<custom-code-component> error during import from ${t}@${e}`
589
+ ), h;
590
+ }
591
+ }
592
+ }
593
+ const B = () => customElements.define("custom-code-component", q);
594
+ customElements && !customElements.get("custom-code-component") && B();
595
+ export {
596
+ B as init
597
+ };
598
+ //# sourceMappingURL=index.js.map