clarity-js 0.6.23

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 (87) hide show
  1. package/README.md +26 -0
  2. package/build/clarity.js +4479 -0
  3. package/build/clarity.min.js +1 -0
  4. package/build/clarity.module.js +4473 -0
  5. package/package.json +66 -0
  6. package/rollup.config.ts +38 -0
  7. package/src/clarity.ts +54 -0
  8. package/src/core/config.ts +21 -0
  9. package/src/core/copy.ts +3 -0
  10. package/src/core/event.ts +25 -0
  11. package/src/core/hash.ts +19 -0
  12. package/src/core/history.ts +69 -0
  13. package/src/core/index.ts +79 -0
  14. package/src/core/measure.ts +17 -0
  15. package/src/core/report.ts +27 -0
  16. package/src/core/scrub.ts +102 -0
  17. package/src/core/task.ts +180 -0
  18. package/src/core/time.ts +14 -0
  19. package/src/core/timeout.ts +10 -0
  20. package/src/core/version.ts +2 -0
  21. package/src/data/baseline.ts +89 -0
  22. package/src/data/compress.ts +31 -0
  23. package/src/data/custom.ts +18 -0
  24. package/src/data/dimension.ts +42 -0
  25. package/src/data/encode.ts +109 -0
  26. package/src/data/envelope.ts +46 -0
  27. package/src/data/index.ts +43 -0
  28. package/src/data/limit.ts +42 -0
  29. package/src/data/metadata.ts +232 -0
  30. package/src/data/metric.ts +51 -0
  31. package/src/data/ping.ts +36 -0
  32. package/src/data/summary.ts +34 -0
  33. package/src/data/token.ts +39 -0
  34. package/src/data/upgrade.ts +36 -0
  35. package/src/data/upload.ts +250 -0
  36. package/src/data/variable.ts +46 -0
  37. package/src/diagnostic/encode.ts +40 -0
  38. package/src/diagnostic/image.ts +23 -0
  39. package/src/diagnostic/index.ts +14 -0
  40. package/src/diagnostic/internal.ts +41 -0
  41. package/src/diagnostic/script.ts +45 -0
  42. package/src/global.ts +22 -0
  43. package/src/index.ts +8 -0
  44. package/src/interaction/click.ts +140 -0
  45. package/src/interaction/encode.ts +140 -0
  46. package/src/interaction/index.ts +45 -0
  47. package/src/interaction/input.ts +64 -0
  48. package/src/interaction/pointer.ts +108 -0
  49. package/src/interaction/resize.ts +30 -0
  50. package/src/interaction/scroll.ts +73 -0
  51. package/src/interaction/selection.ts +66 -0
  52. package/src/interaction/timeline.ts +65 -0
  53. package/src/interaction/unload.ts +25 -0
  54. package/src/interaction/visibility.ts +24 -0
  55. package/src/layout/box.ts +83 -0
  56. package/src/layout/discover.ts +27 -0
  57. package/src/layout/document.ts +46 -0
  58. package/src/layout/dom.ts +442 -0
  59. package/src/layout/encode.ts +111 -0
  60. package/src/layout/extract.ts +75 -0
  61. package/src/layout/index.ts +25 -0
  62. package/src/layout/mutation.ts +232 -0
  63. package/src/layout/node.ts +211 -0
  64. package/src/layout/offset.ts +19 -0
  65. package/src/layout/region.ts +143 -0
  66. package/src/layout/schema.ts +66 -0
  67. package/src/layout/selector.ts +24 -0
  68. package/src/layout/target.ts +44 -0
  69. package/src/layout/traverse.ts +28 -0
  70. package/src/performance/connection.ts +37 -0
  71. package/src/performance/encode.ts +40 -0
  72. package/src/performance/index.ts +15 -0
  73. package/src/performance/navigation.ts +31 -0
  74. package/src/performance/observer.ts +87 -0
  75. package/test/core.test.ts +82 -0
  76. package/test/helper.ts +104 -0
  77. package/test/html/core.html +17 -0
  78. package/test/tsconfig.test.json +6 -0
  79. package/tsconfig.json +21 -0
  80. package/tslint.json +33 -0
  81. package/types/core.d.ts +127 -0
  82. package/types/data.d.ts +344 -0
  83. package/types/diagnostic.d.ts +24 -0
  84. package/types/index.d.ts +30 -0
  85. package/types/interaction.d.ts +110 -0
  86. package/types/layout.d.ts +200 -0
  87. package/types/performance.d.ts +40 -0
@@ -0,0 +1,4473 @@
1
+ var upload$1 = /*#__PURE__*/Object.freeze({
2
+ __proto__: null,
3
+ get track () { return track; },
4
+ get start () { return start$a; },
5
+ get queue () { return queue; },
6
+ get stop () { return stop$9; }
7
+ });
8
+
9
+ var config$1 = {
10
+ projectId: null,
11
+ delay: 1 * 1000 /* Second */,
12
+ cssRules: false,
13
+ lean: false,
14
+ track: true,
15
+ content: true,
16
+ mask: [],
17
+ unmask: [],
18
+ regions: [],
19
+ metrics: [],
20
+ cookies: [],
21
+ report: null,
22
+ upload: null,
23
+ fallback: null,
24
+ upgrade: null
25
+ };
26
+
27
+ var startTime = 0;
28
+ function start$E() {
29
+ startTime = performance.now();
30
+ }
31
+ function time(ts) {
32
+ if (ts === void 0) { ts = null; }
33
+ ts = ts ? ts : performance.now();
34
+ return Math.max(Math.round(ts - startTime), 0);
35
+ }
36
+ function stop$B() {
37
+ startTime = 0;
38
+ }
39
+
40
+ var state$7 = null;
41
+ var buffer = null;
42
+ var update$1 = false;
43
+ function start$D() {
44
+ update$1 = false;
45
+ reset$n();
46
+ }
47
+ function reset$n() {
48
+ // Baseline state holds the previous values - if it is updated in the current payload,
49
+ // reset the state to current value after sending the previous state
50
+ if (update$1) {
51
+ state$7 = { time: time(), event: 4 /* Baseline */, data: {
52
+ visible: buffer.visible,
53
+ docWidth: buffer.docWidth,
54
+ docHeight: buffer.docHeight,
55
+ screenWidth: buffer.screenWidth,
56
+ screenHeight: buffer.screenHeight,
57
+ scrollX: buffer.scrollX,
58
+ scrollY: buffer.scrollY,
59
+ pointerX: buffer.pointerX,
60
+ pointerY: buffer.pointerY,
61
+ activityTime: buffer.activityTime
62
+ }
63
+ };
64
+ }
65
+ buffer = buffer ? buffer : {
66
+ visible: 1 /* True */,
67
+ docWidth: 0,
68
+ docHeight: 0,
69
+ screenWidth: 0,
70
+ screenHeight: 0,
71
+ scrollX: 0,
72
+ scrollY: 0,
73
+ pointerX: 0,
74
+ pointerY: 0,
75
+ activityTime: 0
76
+ };
77
+ }
78
+ function track$7(event, x, y) {
79
+ switch (event) {
80
+ case 8 /* Document */:
81
+ buffer.docWidth = x;
82
+ buffer.docHeight = y;
83
+ break;
84
+ case 11 /* Resize */:
85
+ buffer.screenWidth = x;
86
+ buffer.screenHeight = y;
87
+ break;
88
+ case 10 /* Scroll */:
89
+ buffer.scrollX = x;
90
+ buffer.scrollY = y;
91
+ break;
92
+ default:
93
+ buffer.pointerX = x;
94
+ buffer.pointerY = y;
95
+ break;
96
+ }
97
+ update$1 = true;
98
+ }
99
+ function activity(t) {
100
+ buffer.activityTime = t;
101
+ }
102
+ function visibility(t, visible) {
103
+ buffer.visible = visible === "visible" ? 1 /* True */ : 0 /* False */;
104
+ if (!buffer.visible) {
105
+ activity(t);
106
+ }
107
+ update$1 = true;
108
+ }
109
+ function compute$c() {
110
+ if (update$1) {
111
+ encode$1(4 /* Baseline */);
112
+ }
113
+ }
114
+ function stop$A() {
115
+ reset$n();
116
+ }
117
+
118
+ var baseline = /*#__PURE__*/Object.freeze({
119
+ __proto__: null,
120
+ get state () { return state$7; },
121
+ start: start$D,
122
+ reset: reset$n,
123
+ track: track$7,
124
+ activity: activity,
125
+ visibility: visibility,
126
+ compute: compute$c,
127
+ stop: stop$A
128
+ });
129
+
130
+ var data$k = null;
131
+ function event(key, value) {
132
+ if (active() &&
133
+ key &&
134
+ value &&
135
+ typeof key === "string" /* String */ &&
136
+ typeof value === "string" /* String */ &&
137
+ key.length < 255 &&
138
+ value.length < 255) {
139
+ data$k = { key: key, value: value };
140
+ encode$1(24 /* Custom */);
141
+ }
142
+ }
143
+
144
+ // tslint:disable: no-bitwise
145
+ function hash (input) {
146
+ // Code inspired from C# GetHashCode: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs
147
+ var hash = 0;
148
+ var hashOne = 5381;
149
+ var hashTwo = hashOne;
150
+ for (var i = 0; i < input.length; i += 2) {
151
+ var charOne = input.charCodeAt(i);
152
+ hashOne = ((hashOne << 5) + hashOne) ^ charOne;
153
+ if (i + 1 < input.length) {
154
+ var charTwo = input.charCodeAt(i + 1);
155
+ hashTwo = ((hashTwo << 5) + hashTwo) ^ charTwo;
156
+ }
157
+ }
158
+ // Replace the magic number from C# implementation (1566083941) with a smaller prime number (11579)
159
+ // This ensures we don't hit integer overflow and prevent collisions
160
+ hash = Math.abs(hashOne + (hashTwo * 11579));
161
+ return hash.toString(36);
162
+ }
163
+
164
+ var data$j = null;
165
+ function start$C() {
166
+ reset$m();
167
+ }
168
+ function set(variable, value) {
169
+ var values = typeof value === "string" /* String */ ? [value] : value;
170
+ log$2(variable, values);
171
+ }
172
+ function identify(userId, sessionId, pageId) {
173
+ if (sessionId === void 0) { sessionId = null; }
174
+ if (pageId === void 0) { pageId = null; }
175
+ log$2("userId" /* UserId */, [userId]);
176
+ log$2("sessionId" /* SessionId */, [sessionId]);
177
+ log$2("pageId" /* PageId */, [pageId]);
178
+ }
179
+ function log$2(variable, value) {
180
+ if (active() &&
181
+ variable &&
182
+ value &&
183
+ typeof variable === "string" /* String */ &&
184
+ variable.length < 255) {
185
+ var validValues = variable in data$j ? data$j[variable] : [];
186
+ for (var i = 0; i < value.length; i++) {
187
+ if (typeof value[i] === "string" /* String */ && value[i].length < 255) {
188
+ validValues.push(value[i]);
189
+ }
190
+ }
191
+ data$j[variable] = validValues;
192
+ }
193
+ }
194
+ function compute$b() {
195
+ encode$1(34 /* Variable */);
196
+ }
197
+ function reset$m() {
198
+ data$j = {};
199
+ }
200
+ function stop$z() {
201
+ reset$m();
202
+ }
203
+
204
+ var variable = /*#__PURE__*/Object.freeze({
205
+ __proto__: null,
206
+ get data () { return data$j; },
207
+ start: start$C,
208
+ set: set,
209
+ identify: identify,
210
+ compute: compute$b,
211
+ reset: reset$m,
212
+ stop: stop$z
213
+ });
214
+
215
+ var data$i = null;
216
+ var callback = null;
217
+ var rootDomain = null;
218
+ function start$B() {
219
+ callback = null;
220
+ rootDomain = null;
221
+ var ua = navigator && "userAgent" in navigator ? navigator.userAgent : "" /* Empty */;
222
+ var title = document && document.title ? document.title : "" /* Empty */;
223
+ // Populate ids for this page
224
+ var s = session();
225
+ var u = user();
226
+ data$i = {
227
+ projectId: config$1.projectId || hash(location.host),
228
+ userId: u.id,
229
+ sessionId: s.session,
230
+ pageNum: s.count
231
+ };
232
+ // Override configuration based on what's in the session storage
233
+ config$1.lean = config$1.track && s.upgrade !== null ? s.upgrade === 0 /* False */ : config$1.lean;
234
+ config$1.upload = config$1.track && typeof config$1.upload === "string" /* String */ && s.upload ? s.upload : config$1.upload;
235
+ // Log dimensions
236
+ log$1(0 /* UserAgent */, ua);
237
+ log$1(3 /* PageTitle */, title);
238
+ log$1(1 /* Url */, location.href);
239
+ log$1(2 /* Referrer */, document.referrer);
240
+ log$1(15 /* TabId */, tab());
241
+ log$1(16 /* PageLanguage */, document.documentElement.lang);
242
+ log$1(17 /* DocumentDirection */, document.dir);
243
+ if (navigator) {
244
+ log$1(9 /* Language */, navigator.userLanguage || navigator.language);
245
+ }
246
+ // Metrics
247
+ max(0 /* ClientTimestamp */, s.ts);
248
+ max(1 /* Playback */, 0 /* False */);
249
+ if (screen) {
250
+ max(14 /* ScreenWidth */, Math.round(screen.width));
251
+ max(15 /* ScreenHeight */, Math.round(screen.height));
252
+ max(16 /* ColorDepth */, Math.round(screen.colorDepth));
253
+ }
254
+ // Read cookies specified in configuration
255
+ for (var _i = 0, _a = config$1.cookies; _i < _a.length; _i++) {
256
+ var key = _a[_i];
257
+ var value = getCookie(key);
258
+ if (value) {
259
+ set(key, value);
260
+ }
261
+ }
262
+ // Track ids using a cookie if configuration allows it
263
+ track$6(u);
264
+ }
265
+ function stop$y() {
266
+ callback = null;
267
+ rootDomain = null;
268
+ }
269
+ function metadata$2(cb) {
270
+ callback = cb;
271
+ }
272
+ function id() {
273
+ return data$i ? [data$i.userId, data$i.sessionId, data$i.pageNum].join("." /* Dot */) : "" /* Empty */;
274
+ }
275
+ function consent() {
276
+ if (active()) {
277
+ config$1.track = true;
278
+ track$6(user(), 1 /* True */);
279
+ }
280
+ }
281
+ function clear() {
282
+ // Clear any stored information in the cookie that tracks session information so we can restart fresh the next time
283
+ setCookie("_clsk" /* SessionKey */, "" /* Empty */, 0);
284
+ }
285
+ function tab() {
286
+ var id = shortid();
287
+ if (config$1.track && supported$1(window, "sessionStorage" /* SessionStorage */)) {
288
+ var value = sessionStorage.getItem("_cltk" /* TabKey */);
289
+ id = value ? value : id;
290
+ sessionStorage.setItem("_cltk" /* TabKey */, id);
291
+ }
292
+ return id;
293
+ }
294
+ function save() {
295
+ var ts = Math.round(Date.now());
296
+ var upgrade = config$1.lean ? 0 /* False */ : 1 /* True */;
297
+ var upload = config$1.upload && typeof config$1.upload === "string" /* String */ ? config$1.upload.replace("https://" /* HTTPS */, "" /* Empty */) : "" /* Empty */;
298
+ if (upgrade && callback) {
299
+ callback(data$i, !config$1.lean);
300
+ }
301
+ setCookie("_clsk" /* SessionKey */, [data$i.sessionId, ts, data$i.pageNum, upgrade, upload].join("|" /* Pipe */), 1 /* SessionExpire */);
302
+ }
303
+ function supported$1(target, api) {
304
+ try {
305
+ return !!target[api];
306
+ }
307
+ catch (_a) {
308
+ return false;
309
+ }
310
+ }
311
+ function track$6(u, consent) {
312
+ if (consent === void 0) { consent = null; }
313
+ // If consent is not explicitly specified, infer it from the user object
314
+ consent = consent === null ? u.consent : consent;
315
+ // Convert time precision into days to reduce number of bytes we have to write in a cookie
316
+ // E.g. Math.ceil(1628735962643 / (24*60*60*1000)) => 18852 (days) => ejo in base36 (13 bytes => 3 bytes)
317
+ var end = Math.ceil((Date.now() + (365 /* Expire */ * 86400000 /* Day */)) / 86400000 /* Day */);
318
+ // To avoid cookie churn, write user id cookie only once every day
319
+ if (u.expiry === null || Math.abs(end - u.expiry) >= 1 /* CookieInterval */ || u.consent !== consent) {
320
+ setCookie("_clck" /* CookieKey */, [data$i.userId, 1 /* CookieVersion */, end.toString(36), consent].join("|" /* Pipe */), 365 /* Expire */);
321
+ }
322
+ }
323
+ function shortid() {
324
+ var id = Math.floor(Math.random() * Math.pow(2, 32));
325
+ if (window && window.crypto && window.crypto.getRandomValues && Uint32Array) {
326
+ id = window.crypto.getRandomValues(new Uint32Array(1))[0];
327
+ }
328
+ return id.toString(36);
329
+ }
330
+ function session() {
331
+ var output = { session: shortid(), ts: Math.round(Date.now()), count: 1, upgrade: null, upload: "" /* Empty */ };
332
+ var value = getCookie("_clsk" /* SessionKey */);
333
+ if (value) {
334
+ var parts = value.split("|" /* Pipe */);
335
+ // Making it backward & forward compatible by using greater than comparison (v0.6.21)
336
+ // In future version, we can reduce the parts length to be 5 where the last part contains the full upload URL
337
+ if (parts.length >= 5 && output.ts - num$2(parts[1]) < 1800000 /* SessionTimeout */) {
338
+ output.session = parts[0];
339
+ output.count = num$2(parts[2]) + 1;
340
+ output.upgrade = num$2(parts[3]);
341
+ output.upload = parts.length >= 6 ? "" + "https://" /* HTTPS */ + parts[5] + "/" + parts[4] : "" + "https://" /* HTTPS */ + parts[4];
342
+ }
343
+ }
344
+ return output;
345
+ }
346
+ function num$2(string, base) {
347
+ if (base === void 0) { base = 10; }
348
+ return parseInt(string, base);
349
+ }
350
+ function user() {
351
+ var output = { id: shortid(), expiry: null, consent: 0 /* False */ };
352
+ var cookie = getCookie("_clck" /* CookieKey */);
353
+ if (cookie && cookie.length > 0) {
354
+ // Splitting and looking up first part for forward compatibility, in case we wish to store additional information in a cookie
355
+ var parts = cookie.split("|" /* Pipe */);
356
+ // For backward compatibility introduced in v0.6.18; following code can be removed with future iterations
357
+ // Count number of times Clarity's user cookie crumb appears in document.cookie (could be on different sub-domains e.g. www.domain.com and .domain.com)
358
+ var count = 0;
359
+ for (var _i = 0, _a = document.cookie.split(";" /* Semicolon */); _i < _a.length; _i++) {
360
+ var c = _a[_i];
361
+ count += c.split("=" /* Equals */)[0].trim() === "_clck" /* CookieKey */ ? 1 : 0;
362
+ }
363
+ // Check if we either got version-less cookie value or saw multiple copies of the user cookie crumbs
364
+ // In both these cases, we go ahead and delete the existing cookie set on current domain
365
+ if (parts.length === 1 || count > 1) {
366
+ var deleted = "" + ";" /* Semicolon */ + "expires=" /* Expires */ + (new Date(0)).toUTCString() + ";path=/" /* Path */;
367
+ // First, delete current user cookie which might be set on current sub-domain vs. root domain
368
+ document.cookie = "_clck" /* CookieKey */ + "=" + deleted;
369
+ // Second, same thing for current session cookie so it can be re-written later with the root domain
370
+ document.cookie = "_clsk" /* SessionKey */ + "=" + deleted;
371
+ }
372
+ // End code for backward compatibility
373
+ // Read version information and timestamp from cookie, if available
374
+ if (parts.length > 2) {
375
+ output.expiry = num$2(parts[2], 36);
376
+ }
377
+ // Check if we have explicit consent to track this user
378
+ if (parts.length > 3 && num$2(parts[3]) === 1) {
379
+ output.consent = 1 /* True */;
380
+ }
381
+ // Set track configuration to true for this user if we have explicit consent, regardless of project setting
382
+ config$1.track = config$1.track || output.consent === 1 /* True */;
383
+ // Get user id from cookie only if we tracking is enabled, otherwise fallback to a random id
384
+ output.id = config$1.track ? parts[0] : output.id;
385
+ }
386
+ return output;
387
+ }
388
+ function getCookie(key) {
389
+ if (supported$1(document, "cookie" /* Cookie */)) {
390
+ var cookies = document.cookie.split(";" /* Semicolon */);
391
+ if (cookies) {
392
+ for (var i = 0; i < cookies.length; i++) {
393
+ var pair = cookies[i].split("=" /* Equals */);
394
+ if (pair.length > 1 && pair[0] && pair[0].trim() === key) {
395
+ return pair[1];
396
+ }
397
+ }
398
+ }
399
+ }
400
+ return null;
401
+ }
402
+ function setCookie(key, value, time) {
403
+ if (config$1.track && ((navigator && navigator.cookieEnabled) || supported$1(document, "cookie" /* Cookie */))) {
404
+ var expiry = new Date();
405
+ expiry.setDate(expiry.getDate() + time);
406
+ var expires = expiry ? "expires=" /* Expires */ + expiry.toUTCString() : "" /* Empty */;
407
+ var cookie = key + "=" + value + ";" /* Semicolon */ + expires + ";path=/" /* Path */;
408
+ try {
409
+ // Attempt to get the root domain only once and fall back to writing cookie on the current domain.
410
+ if (rootDomain === null) {
411
+ var hostname = location.hostname ? location.hostname.split("." /* Dot */) : [];
412
+ // Walk backwards on a domain and attempt to set a cookie, until successful
413
+ for (var i = hostname.length - 1; i >= 0; i--) {
414
+ rootDomain = "." + hostname[i] + (rootDomain ? rootDomain : "" /* Empty */);
415
+ // We do not wish to attempt writing a cookie on the absolute last part of the domain, e.g. .com or .net.
416
+ // So we start attempting after second-last part, e.g. .domain.com (PASS) or .co.uk (FAIL)
417
+ if (i < hostname.length - 1) {
418
+ // Write the cookie on the current computed top level domain
419
+ document.cookie = "" + cookie + ";" /* Semicolon */ + "domain=" /* Domain */ + rootDomain;
420
+ // Once written, check if the cookie exists and its value matches exactly with what we intended to set
421
+ // Checking for exact value match helps us eliminate a corner case where the cookie may already be present with a different value
422
+ // If the check is successful, no more action is required and we can return from the function since rootDomain cookie is already set
423
+ // If the check fails, continue with the for loop until we can successfully set and verify the cookie
424
+ if (getCookie(key) === value) {
425
+ return;
426
+ }
427
+ }
428
+ }
429
+ // Finally, if we were not successful and gone through all the options, play it safe and reset rootDomain to be empty
430
+ // This forces our code to fall back to always writing cookie to the current domain
431
+ rootDomain = "" /* Empty */;
432
+ }
433
+ }
434
+ catch (_a) {
435
+ rootDomain = "" /* Empty */;
436
+ }
437
+ document.cookie = rootDomain ? "" + cookie + ";" /* Semicolon */ + "domain=" /* Domain */ + rootDomain : cookie;
438
+ }
439
+ }
440
+
441
+ var metadata$3 = /*#__PURE__*/Object.freeze({
442
+ __proto__: null,
443
+ get data () { return data$i; },
444
+ get callback () { return callback; },
445
+ start: start$B,
446
+ stop: stop$y,
447
+ metadata: metadata$2,
448
+ id: id,
449
+ consent: consent,
450
+ clear: clear,
451
+ save: save
452
+ });
453
+
454
+ var history$5;
455
+ function reset$l() {
456
+ history$5 = [];
457
+ }
458
+ function report(check, message) {
459
+ if (message === void 0) { message = null; }
460
+ // Do not report the same message twice for the same page
461
+ if (history$5 && history$5.indexOf(message) === -1) {
462
+ var url = config$1.report;
463
+ if (url && url.length > 0) {
464
+ var payload = { c: check, p: data$i.projectId, u: data$i.userId, s: data$i.sessionId, n: data$i.pageNum };
465
+ if (message)
466
+ payload.m = message;
467
+ // Using POST request instead of a GET request (img-src) to not violate existing CSP rules
468
+ // Since, Clarity already uses XHR to upload data, we stick with similar POST mechanism for reporting too
469
+ var xhr = new XMLHttpRequest();
470
+ xhr.open("POST", url);
471
+ xhr.send(JSON.stringify(payload));
472
+ history$5.push(message);
473
+ }
474
+ }
475
+ }
476
+
477
+ var version$1 = "0.6.23";
478
+
479
+ var data$h = null;
480
+ function start$A() {
481
+ var m = data$i;
482
+ data$h = {
483
+ version: version$1,
484
+ sequence: 0,
485
+ start: 0,
486
+ duration: 0,
487
+ projectId: m.projectId,
488
+ userId: m.userId,
489
+ sessionId: m.sessionId,
490
+ pageNum: m.pageNum,
491
+ upload: 0 /* Async */,
492
+ end: 0 /* False */
493
+ };
494
+ }
495
+ function stop$x() {
496
+ data$h = null;
497
+ }
498
+ function envelope(last) {
499
+ data$h.start = data$h.start + data$h.duration;
500
+ data$h.duration = time() - data$h.start;
501
+ data$h.sequence++;
502
+ data$h.upload = last && "sendBeacon" in navigator ? 1 /* Beacon */ : 0 /* Async */;
503
+ data$h.end = last ? 1 /* True */ : 0 /* False */;
504
+ return [
505
+ data$h.version,
506
+ data$h.sequence,
507
+ data$h.start,
508
+ data$h.duration,
509
+ data$h.projectId,
510
+ data$h.userId,
511
+ data$h.sessionId,
512
+ data$h.pageNum,
513
+ data$h.upload,
514
+ data$h.end
515
+ ];
516
+ }
517
+
518
+ var envelope$1 = /*#__PURE__*/Object.freeze({
519
+ __proto__: null,
520
+ get data () { return data$h; },
521
+ start: start$A,
522
+ stop: stop$x,
523
+ envelope: envelope
524
+ });
525
+
526
+ var data$g;
527
+ function start$z() {
528
+ data$g = { check: 0 /* None */ };
529
+ }
530
+ function check$3(bytes) {
531
+ if (data$g.check === 0 /* None */) {
532
+ var reason = data$g.check;
533
+ reason = data$h.sequence >= 128 /* PayloadLimit */ ? 1 /* Payload */ : reason;
534
+ reason = time() > 7200000 /* ShutdownLimit */ ? 2 /* Shutdown */ : reason;
535
+ reason = bytes > 10485760 /* PlaybackBytesLimit */ ? 2 /* Shutdown */ : reason;
536
+ if (reason !== data$g.check) {
537
+ trigger$1(reason);
538
+ }
539
+ }
540
+ }
541
+ function trigger$1(reason) {
542
+ report(reason);
543
+ data$g.check = reason;
544
+ clear();
545
+ stop();
546
+ }
547
+ function compute$a() {
548
+ if (data$g.check !== 0 /* None */) {
549
+ encode$1(35 /* Limit */);
550
+ }
551
+ }
552
+ function stop$w() {
553
+ data$g = null;
554
+ }
555
+
556
+ var limit = /*#__PURE__*/Object.freeze({
557
+ __proto__: null,
558
+ get data () { return data$g; },
559
+ start: start$z,
560
+ check: check$3,
561
+ trigger: trigger$1,
562
+ compute: compute$a,
563
+ stop: stop$w
564
+ });
565
+
566
+ var data$f = null;
567
+ var updates$3 = null;
568
+ function start$y() {
569
+ data$f = {};
570
+ updates$3 = {};
571
+ }
572
+ function stop$v() {
573
+ data$f = {};
574
+ updates$3 = {};
575
+ }
576
+ function log$1(dimension, value) {
577
+ // Check valid value before moving ahead
578
+ if (value) {
579
+ // Ensure received value is casted into a string if it wasn't a string to begin with
580
+ value = "" + value;
581
+ if (!(dimension in data$f)) {
582
+ data$f[dimension] = [];
583
+ }
584
+ if (data$f[dimension].indexOf(value) < 0) {
585
+ data$f[dimension].push(value);
586
+ // If this is a new value, track it as part of updates object
587
+ // This allows us to only send back new values in subsequent payloads
588
+ if (!(dimension in updates$3)) {
589
+ updates$3[dimension] = [];
590
+ }
591
+ updates$3[dimension].push(value);
592
+ // Limit check to ensure we have a cap on number of dimensions we can collect
593
+ if (data$f[dimension].length > 128 /* CollectionLimit */) {
594
+ trigger$1(5 /* Collection */);
595
+ }
596
+ }
597
+ }
598
+ }
599
+ function compute$9() {
600
+ encode$1(1 /* Dimension */);
601
+ }
602
+ function reset$k() {
603
+ updates$3 = {};
604
+ }
605
+
606
+ var dimension = /*#__PURE__*/Object.freeze({
607
+ __proto__: null,
608
+ get data () { return data$f; },
609
+ get updates () { return updates$3; },
610
+ start: start$y,
611
+ stop: stop$v,
612
+ log: log$1,
613
+ compute: compute$9,
614
+ reset: reset$k
615
+ });
616
+
617
+ function setTimeout(handler, timeout, event) {
618
+ return window.setTimeout(measure(handler), timeout, event);
619
+ }
620
+ function clearTimeout(handle) {
621
+ return window.clearTimeout(handle);
622
+ }
623
+
624
+ var data$e;
625
+ var last = 0;
626
+ var interval = 0;
627
+ var timeout$6 = null;
628
+ function start$x() {
629
+ interval = 60000 /* PingInterval */;
630
+ last = 0;
631
+ }
632
+ function reset$j() {
633
+ if (timeout$6) {
634
+ clearTimeout(timeout$6);
635
+ }
636
+ timeout$6 = setTimeout(ping, interval);
637
+ last = time();
638
+ }
639
+ function ping() {
640
+ var now = time();
641
+ data$e = { gap: now - last };
642
+ encode$1(25 /* Ping */);
643
+ if (data$e.gap < 300000 /* PingTimeout */) {
644
+ timeout$6 = setTimeout(ping, interval);
645
+ }
646
+ else {
647
+ suspend();
648
+ }
649
+ }
650
+ function stop$u() {
651
+ clearTimeout(timeout$6);
652
+ last = 0;
653
+ interval = 0;
654
+ }
655
+
656
+ var ping$1 = /*#__PURE__*/Object.freeze({
657
+ __proto__: null,
658
+ get data () { return data$e; },
659
+ start: start$x,
660
+ reset: reset$j,
661
+ stop: stop$u
662
+ });
663
+
664
+ var data$d = null;
665
+ function start$w() {
666
+ data$d = {};
667
+ }
668
+ function stop$t() {
669
+ data$d = {};
670
+ }
671
+ function track$5(event, time) {
672
+ if (!(event in data$d)) {
673
+ data$d[event] = [[time, 0]];
674
+ }
675
+ else {
676
+ var e = data$d[event];
677
+ var last = e[e.length - 1];
678
+ // Add a new entry only if the new event occurs after configured interval
679
+ // Otherwise, extend the duration of the previous entry
680
+ if (time - last[0] > 100 /* SummaryInterval */) {
681
+ data$d[event].push([time, 0]);
682
+ }
683
+ else {
684
+ last[1] = time - last[0];
685
+ }
686
+ }
687
+ }
688
+ function compute$8() {
689
+ encode$1(36 /* Summary */);
690
+ }
691
+ function reset$i() {
692
+ data$d = {};
693
+ }
694
+
695
+ var summary = /*#__PURE__*/Object.freeze({
696
+ __proto__: null,
697
+ get data () { return data$d; },
698
+ start: start$w,
699
+ stop: stop$t,
700
+ track: track$5,
701
+ compute: compute$8,
702
+ reset: reset$i
703
+ });
704
+
705
+ var data$c = null;
706
+ function start$v() {
707
+ if (!config$1.lean && config$1.upgrade) {
708
+ config$1.upgrade("Config" /* Config */);
709
+ }
710
+ data$c = null;
711
+ }
712
+ // Following call will upgrade the session from lean mode into the full mode retroactively from the start of the page.
713
+ // As part of the lean mode, we do not send back any layout information - including discovery of DOM and mutations.
714
+ // However, if there's a need for full fidelity playback, calling this function will disable lean mode
715
+ // and send all backed up layout events to the server.
716
+ function upgrade(key) {
717
+ // Upgrade only if Clarity was successfully activated on the page
718
+ if (active() && config$1.lean) {
719
+ config$1.lean = false;
720
+ data$c = { key: key };
721
+ // Update metadata to track we have upgraded this session
722
+ save();
723
+ // Callback upgrade handler, if configured
724
+ if (config$1.upgrade) {
725
+ config$1.upgrade(key);
726
+ }
727
+ encode$1(3 /* Upgrade */);
728
+ }
729
+ }
730
+ function stop$s() {
731
+ data$c = null;
732
+ }
733
+
734
+ var upgrade$1 = /*#__PURE__*/Object.freeze({
735
+ __proto__: null,
736
+ get data () { return data$c; },
737
+ start: start$v,
738
+ upgrade: upgrade,
739
+ stop: stop$s
740
+ });
741
+
742
+ /*! *****************************************************************************
743
+ Copyright (c) Microsoft Corporation.
744
+
745
+ Permission to use, copy, modify, and/or distribute this software for any
746
+ purpose with or without fee is hereby granted.
747
+
748
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
749
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
750
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
751
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
752
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
753
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
754
+ PERFORMANCE OF THIS SOFTWARE.
755
+ ***************************************************************************** */
756
+
757
+ function __awaiter(thisArg, _arguments, P, generator) {
758
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
759
+ return new (P || (P = Promise))(function (resolve, reject) {
760
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
761
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
762
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
763
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
764
+ });
765
+ }
766
+
767
+ function __generator(thisArg, body) {
768
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
769
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
770
+ function verb(n) { return function (v) { return step([n, v]); }; }
771
+ function step(op) {
772
+ if (f) throw new TypeError("Generator is already executing.");
773
+ while (_) try {
774
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
775
+ if (y = 0, t) op = [op[0] & 2, t.value];
776
+ switch (op[0]) {
777
+ case 0: case 1: t = op; break;
778
+ case 4: _.label++; return { value: op[1], done: false };
779
+ case 5: _.label++; y = op[1]; op = [0]; continue;
780
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
781
+ default:
782
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
783
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
784
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
785
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
786
+ if (t[2]) _.ops.pop();
787
+ _.trys.pop(); continue;
788
+ }
789
+ op = body.call(thisArg, _);
790
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
791
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
792
+ }
793
+ }
794
+
795
+ var supported = "CompressionStream" /* CompressionStream */ in window;
796
+ function compress (input) {
797
+ return __awaiter(this, void 0, void 0, function () {
798
+ var stream, _a;
799
+ return __generator(this, function (_c) {
800
+ switch (_c.label) {
801
+ case 0:
802
+ _c.trys.push([0, 3, , 4]);
803
+ if (!supported) return [3 /*break*/, 2];
804
+ stream = new ReadableStream({ start: function (controller) {
805
+ return __awaiter(this, void 0, void 0, function () {
806
+ return __generator(this, function (_a) {
807
+ controller.enqueue(input);
808
+ controller.close();
809
+ return [2 /*return*/];
810
+ });
811
+ });
812
+ } }).pipeThrough(new TextEncoderStream()).pipeThrough(new window["CompressionStream" /* CompressionStream */]("gzip"));
813
+ _a = Uint8Array.bind;
814
+ return [4 /*yield*/, read(stream)];
815
+ case 1: return [2 /*return*/, new (_a.apply(Uint8Array, [void 0, _c.sent()]))()];
816
+ case 2: return [3 /*break*/, 4];
817
+ case 3:
818
+ _c.sent();
819
+ return [3 /*break*/, 4];
820
+ case 4: return [2 /*return*/, null];
821
+ }
822
+ });
823
+ });
824
+ }
825
+ function read(stream) {
826
+ return __awaiter(this, void 0, void 0, function () {
827
+ var reader, chunks, done, value;
828
+ var _a;
829
+ return __generator(this, function (_b) {
830
+ switch (_b.label) {
831
+ case 0:
832
+ reader = stream.getReader();
833
+ chunks = [];
834
+ done = false;
835
+ value = [];
836
+ _b.label = 1;
837
+ case 1:
838
+ if (!!done) return [3 /*break*/, 3];
839
+ return [4 /*yield*/, reader.read()];
840
+ case 2:
841
+ (_a = _b.sent(), done = _a.done, value = _a.value);
842
+ if (done) {
843
+ return [2 /*return*/, chunks];
844
+ }
845
+ chunks.push.apply(chunks, value);
846
+ return [3 /*break*/, 1];
847
+ case 3: return [2 /*return*/, chunks];
848
+ }
849
+ });
850
+ });
851
+ }
852
+
853
+ var modules$1 = [baseline, dimension, variable, limit, summary, metadata$3, envelope$1, upload$1, ping$1, upgrade$1];
854
+ function start$u() {
855
+ // Metric needs to be initialized before we can start measuring. so metric is not wrapped in measure
856
+ start$9();
857
+ modules$1.forEach(function (x) { return measure(x.start)(); });
858
+ }
859
+ function stop$r() {
860
+ // Stop modules in the reverse order of their initialization
861
+ // The ordering below should respect inter-module dependency.
862
+ // E.g. if upgrade depends on upload, then upgrade needs to end before upload.
863
+ // Similarly, if upload depends on metadata, upload needs to end before metadata.
864
+ modules$1.slice().reverse().forEach(function (x) { return measure(x.stop)(); });
865
+ stop$8();
866
+ }
867
+ function compute$7() {
868
+ compute$b();
869
+ compute$c();
870
+ compute$9();
871
+ compute$2();
872
+ compute$8();
873
+ compute$a();
874
+ }
875
+
876
+ function scrub (value, hint, privacy, mangle) {
877
+ if (mangle === void 0) { mangle = false; }
878
+ if (value) {
879
+ switch (privacy) {
880
+ case 0 /* None */:
881
+ return value;
882
+ case 1 /* Sensitive */:
883
+ switch (hint) {
884
+ case "*T" /* TextTag */:
885
+ case "value":
886
+ case "placeholder":
887
+ return redact(value);
888
+ case "input":
889
+ return mangleToken(value);
890
+ }
891
+ return value;
892
+ case 2 /* Text */:
893
+ case 3 /* TextImage */:
894
+ switch (hint) {
895
+ case "*T" /* TextTag */:
896
+ return mangle ? mangleText(value) : mask(value);
897
+ case "src":
898
+ case "srcset":
899
+ case "title":
900
+ case "alt":
901
+ return privacy === 3 /* TextImage */ ? "" /* Empty */ : value;
902
+ case "value":
903
+ case "click":
904
+ case "input":
905
+ return mangleToken(value);
906
+ case "placeholder":
907
+ return mask(value);
908
+ }
909
+ break;
910
+ }
911
+ }
912
+ return value;
913
+ }
914
+ function mangleText(value) {
915
+ var trimmed = value.trim();
916
+ if (trimmed.length > 0) {
917
+ var first = trimmed[0];
918
+ var index = value.indexOf(first);
919
+ var prefix = value.substr(0, index);
920
+ var suffix = value.substr(index + trimmed.length);
921
+ return "" + prefix + trimmed.length.toString(36) + suffix;
922
+ }
923
+ return value;
924
+ }
925
+ function mask(value) {
926
+ return value.replace(/\S/gi, "\u2022" /* Mask */);
927
+ }
928
+ function mangleToken(value) {
929
+ var length = ((Math.floor(value.length / 5 /* WordLength */) + 1) * 5 /* WordLength */);
930
+ var output = "" /* Empty */;
931
+ for (var i = 0; i < length; i++) {
932
+ output += i > 0 && i % 5 /* WordLength */ === 0 ? " " /* Space */ : "\u2022" /* Mask */;
933
+ }
934
+ return output;
935
+ }
936
+ function redact(value) {
937
+ var spaceIndex = -1;
938
+ var hasDigit = false;
939
+ var hasEmail = false;
940
+ var hasWhitespace = false;
941
+ var array = null;
942
+ for (var i = 0; i < value.length; i++) {
943
+ var c = value.charCodeAt(i);
944
+ hasDigit = hasDigit || (c >= 48 && c <= 57); // Check for digits in the current word
945
+ hasEmail = hasEmail || c === 64; // Check for @ sign anywhere within the current word
946
+ hasWhitespace = c === 9 || c === 10 || c === 13 || c === 32; // Whitespace character (32: blank space | 9: \t | 10: \n | 13: \r)
947
+ // Process each word as an individual token to redact any sensitive information
948
+ if (i === 0 || i === value.length - 1 || hasWhitespace) {
949
+ // Performance optimization: Lazy load string -> array conversion only when required
950
+ if (hasDigit || hasEmail) {
951
+ if (array === null) {
952
+ array = value.split("" /* Empty */);
953
+ }
954
+ mutate(array, spaceIndex, hasWhitespace ? i : i + 1);
955
+ }
956
+ // Reset digit and email flags after every word boundary, except the beginning of string
957
+ if (hasWhitespace) {
958
+ hasDigit = false;
959
+ hasEmail = false;
960
+ spaceIndex = i;
961
+ }
962
+ }
963
+ }
964
+ return array ? array.join("" /* Empty */) : value;
965
+ }
966
+ function mutate(array, start, end) {
967
+ for (var i = start + 1; i < end; i++) {
968
+ array[i] = "\u2022" /* Mask */;
969
+ }
970
+ }
971
+
972
+ // Track the start time to be able to compute duration at the end of the task
973
+ var idleTimeout = 5000;
974
+ var tracker = {};
975
+ var queuedTasks = [];
976
+ var activeTask = null;
977
+ var pauseTask = null;
978
+ var resumeResolve = null;
979
+ function pause$1() {
980
+ if (pauseTask === null) {
981
+ pauseTask = new Promise(function (resolve) {
982
+ resumeResolve = resolve;
983
+ });
984
+ }
985
+ }
986
+ function resume$1() {
987
+ if (pauseTask) {
988
+ resumeResolve();
989
+ pauseTask = null;
990
+ if (activeTask === null) {
991
+ run();
992
+ }
993
+ }
994
+ }
995
+ function reset$h() {
996
+ tracker = {};
997
+ queuedTasks = [];
998
+ activeTask = null;
999
+ pauseTask = null;
1000
+ }
1001
+ function schedule$1(task, priority) {
1002
+ if (priority === void 0) { priority = 0 /* Normal */; }
1003
+ return __awaiter(this, void 0, void 0, function () {
1004
+ var _i, queuedTasks_1, q, promise;
1005
+ return __generator(this, function (_a) {
1006
+ // If this task is already scheduled, skip it
1007
+ for (_i = 0, queuedTasks_1 = queuedTasks; _i < queuedTasks_1.length; _i++) {
1008
+ q = queuedTasks_1[_i];
1009
+ if (q.task === task) {
1010
+ return [2 /*return*/];
1011
+ }
1012
+ }
1013
+ promise = new Promise(function (resolve) {
1014
+ var insert = priority === 1 /* High */ ? "unshift" : "push";
1015
+ // Queue this task for asynchronous execution later
1016
+ // We also store a unique page identifier (id) along with the task to ensure
1017
+ // ensure that we do not accidentally execute this task in context of a different page
1018
+ queuedTasks[insert]({ task: task, resolve: resolve, id: id() });
1019
+ });
1020
+ // If there is no active task running, and Clarity is not in pause state,
1021
+ // invoke the first task in the queue synchronously. This ensures that we don't yield the thread during unload event
1022
+ if (activeTask === null && pauseTask === null) {
1023
+ run();
1024
+ }
1025
+ return [2 /*return*/, promise];
1026
+ });
1027
+ });
1028
+ }
1029
+ function run() {
1030
+ var entry = queuedTasks.shift();
1031
+ if (entry) {
1032
+ activeTask = entry;
1033
+ entry.task().then(function () {
1034
+ // Bail out if the context in which this task was operating is different from the current page
1035
+ // An example scenario where task could span across pages is Single Page Applications (SPA)
1036
+ // A task that started on page #1, but completes on page #2
1037
+ if (entry.id !== id()) {
1038
+ return;
1039
+ }
1040
+ entry.resolve();
1041
+ activeTask = null; // Reset active task back to null now that the promise is resolved
1042
+ run();
1043
+ }).catch(function (error) {
1044
+ // If one of the scheduled tasks failed, log, recover and continue processing rest of the tasks
1045
+ if (entry.id !== id()) {
1046
+ return;
1047
+ }
1048
+ if (error) {
1049
+ log(0 /* RunTask */, 1 /* Warning */, error.name, error.message, error.stack);
1050
+ }
1051
+ activeTask = null;
1052
+ run();
1053
+ });
1054
+ }
1055
+ }
1056
+ function state$6(timer) {
1057
+ var id = key(timer);
1058
+ if (id in tracker) {
1059
+ var elapsed = performance.now() - tracker[id].start;
1060
+ return (elapsed > tracker[id].yield) ? 0 /* Wait */ : 1 /* Run */;
1061
+ }
1062
+ // If this task is no longer being tracked, send stop message to the caller
1063
+ return 2 /* Stop */;
1064
+ }
1065
+ function start$t(timer) {
1066
+ tracker[key(timer)] = { start: performance.now(), calls: 0, yield: 30 /* LongTask */ };
1067
+ }
1068
+ function restart$1(timer) {
1069
+ var id = key(timer);
1070
+ if (tracker && tracker[id]) {
1071
+ var c = tracker[id].calls;
1072
+ var y = tracker[id].yield;
1073
+ start$t(timer);
1074
+ tracker[id].calls = c + 1;
1075
+ tracker[id].yield = y;
1076
+ }
1077
+ }
1078
+ function stop$q(timer) {
1079
+ var end = performance.now();
1080
+ var id = key(timer);
1081
+ var duration = end - tracker[id].start;
1082
+ sum(timer.cost, duration);
1083
+ count$1(5 /* InvokeCount */);
1084
+ // For the first execution, which is synchronous, time is automatically counted towards TotalDuration.
1085
+ // However, for subsequent asynchronous runs, we need to manually update TotalDuration metric.
1086
+ if (tracker[id].calls > 0) {
1087
+ sum(4 /* TotalCost */, duration);
1088
+ }
1089
+ }
1090
+ function suspend$1(timer) {
1091
+ return __awaiter(this, void 0, void 0, function () {
1092
+ var id, _a;
1093
+ return __generator(this, function (_b) {
1094
+ switch (_b.label) {
1095
+ case 0:
1096
+ id = key(timer);
1097
+ if (!(id in tracker)) return [3 /*break*/, 2];
1098
+ stop$q(timer);
1099
+ _a = tracker[id];
1100
+ return [4 /*yield*/, wait()];
1101
+ case 1:
1102
+ _a.yield = (_b.sent()).timeRemaining();
1103
+ restart$1(timer);
1104
+ _b.label = 2;
1105
+ case 2:
1106
+ // After we are done with suspending task, ensure that we are still operating in the right context
1107
+ // If the task is still being tracked, continue running the task, otherwise ask caller to stop execution
1108
+ return [2 /*return*/, id in tracker ? 1 /* Run */ : 2 /* Stop */];
1109
+ }
1110
+ });
1111
+ });
1112
+ }
1113
+ function key(timer) {
1114
+ return timer.id + "." + timer.cost;
1115
+ }
1116
+ function wait() {
1117
+ return __awaiter(this, void 0, void 0, function () {
1118
+ return __generator(this, function (_a) {
1119
+ switch (_a.label) {
1120
+ case 0:
1121
+ if (!pauseTask) return [3 /*break*/, 2];
1122
+ return [4 /*yield*/, pauseTask];
1123
+ case 1:
1124
+ _a.sent();
1125
+ _a.label = 2;
1126
+ case 2: return [2 /*return*/, new Promise(function (resolve) {
1127
+ requestIdleCallback(resolve, { timeout: idleTimeout });
1128
+ })];
1129
+ }
1130
+ });
1131
+ });
1132
+ }
1133
+ // Use native implementation of requestIdleCallback if it exists.
1134
+ // Otherwise, fall back to a custom implementation using requestAnimationFrame & MessageChannel.
1135
+ // While it's not possible to build a perfect polyfill given the nature of this API, the following code attempts to get close.
1136
+ // Background context: requestAnimationFrame invokes the js code right before: style, layout and paint computation within the frame.
1137
+ // This means, that any code that runs as part of requestAnimationFrame will by default be blocking in nature. Not what we want.
1138
+ // For non-blocking behavior, We need to know when browser has finished painiting. This can be accomplished in two different ways (hacks):
1139
+ // (1) Use MessageChannel to pass the message, and browser will receive the message right after pain event has occured.
1140
+ // (2) Use setTimeout call within requestAnimationFrame. This also works, but there's a risk that browser may throttle setTimeout calls.
1141
+ // Given this information, we are currently using (1) from above. More information on (2) as well as some additional context is below:
1142
+ // https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Performance_best_practices_for_Firefox_fe_engineers
1143
+ function requestIdleCallbackPolyfill(callback, options) {
1144
+ var startTime = performance.now();
1145
+ var channel = new MessageChannel();
1146
+ var incoming = channel.port1;
1147
+ var outgoing = channel.port2;
1148
+ incoming.onmessage = function (event) {
1149
+ var currentTime = performance.now();
1150
+ var elapsed = currentTime - startTime;
1151
+ var duration = currentTime - event.data;
1152
+ if (duration > 30 /* LongTask */ && elapsed < options.timeout) {
1153
+ requestAnimationFrame(function () { outgoing.postMessage(currentTime); });
1154
+ }
1155
+ else {
1156
+ var didTimeout_1 = elapsed > options.timeout;
1157
+ callback({
1158
+ didTimeout: didTimeout_1,
1159
+ timeRemaining: function () { return didTimeout_1 ? 30 /* LongTask */ : Math.max(0, 30 /* LongTask */ - duration); }
1160
+ });
1161
+ }
1162
+ };
1163
+ requestAnimationFrame(function () { outgoing.postMessage(performance.now()); });
1164
+ }
1165
+ var requestIdleCallback = window["requestIdleCallback"] || requestIdleCallbackPolyfill;
1166
+
1167
+ var data$b;
1168
+ function start$s() {
1169
+ bind(document, "error", handler$5, true);
1170
+ }
1171
+ function handler$5(error) {
1172
+ var element = error.target;
1173
+ if (element && element.tagName === "IMG") {
1174
+ data$b = { source: element.src, target: element };
1175
+ schedule$1(encode$3.bind(this, 32 /* ImageError */));
1176
+ }
1177
+ }
1178
+ function stop$p() {
1179
+ data$b = null;
1180
+ }
1181
+
1182
+ // Following code takes an array of tokens and transforms it to optimize for repeating tokens and make it efficient to send over the wire
1183
+ // The way it works is that it iterate over all tokens and checks if the current token was already seen in the tokens array so far
1184
+ // If so, it replaces the token with its reference (index). This helps us save bytes by not repeating the same value twice.
1185
+ // E.g. If tokens array is: ["hello", "world", "coding", "language", "world", "language", "example"]
1186
+ // Then the resulting tokens array after following code execution would be: ["hello", "world", "coding", "language", [1, 3], "example"]
1187
+ // Where [1,3] points to tokens[1] => "world" and tokens[3] => "language"
1188
+ function tokenize (tokens) {
1189
+ var output = [];
1190
+ var lookup = {};
1191
+ var pointer = 0;
1192
+ var reference = null;
1193
+ for (var i = 0; i < tokens.length; i++) {
1194
+ // Only optimize for string values
1195
+ if (typeof tokens[i] === "string" /* String */) {
1196
+ var token = tokens[i];
1197
+ var index = lookup[token] || -1;
1198
+ if (index >= 0) {
1199
+ if (reference) {
1200
+ reference.push(index);
1201
+ }
1202
+ else {
1203
+ reference = [index];
1204
+ output.push(reference);
1205
+ pointer++;
1206
+ }
1207
+ }
1208
+ else {
1209
+ reference = null;
1210
+ output.push(token);
1211
+ lookup[token] = pointer++;
1212
+ }
1213
+ }
1214
+ else {
1215
+ // If the value is anything other than string, append it as it is to the output array
1216
+ // And, also increment the pointer to stay in sync with output array
1217
+ reference = null;
1218
+ output.push(tokens[i]);
1219
+ pointer++;
1220
+ }
1221
+ }
1222
+ return output;
1223
+ }
1224
+
1225
+ var data$a;
1226
+ function reset$g() {
1227
+ data$a = null;
1228
+ }
1229
+ function start$r() {
1230
+ reset$g();
1231
+ compute$6();
1232
+ }
1233
+ function compute$6() {
1234
+ var body = document.body;
1235
+ var d = document.documentElement;
1236
+ var bodyClientWidth = body ? body.clientWidth : null;
1237
+ var bodyScrollWidth = body ? body.scrollWidth : null;
1238
+ var bodyOffsetWidth = body ? body.offsetWidth : null;
1239
+ var documentClientWidth = d ? d.clientWidth : null;
1240
+ var documentScrollWidth = d ? d.scrollWidth : null;
1241
+ var documentOffsetWidth = d ? d.offsetWidth : null;
1242
+ var width = Math.max(bodyClientWidth, bodyScrollWidth, bodyOffsetWidth, documentClientWidth, documentScrollWidth, documentOffsetWidth);
1243
+ var bodyClientHeight = body ? body.clientHeight : null;
1244
+ var bodyScrollHeight = body ? body.scrollHeight : null;
1245
+ var bodyOffsetHeight = body ? body.offsetHeight : null;
1246
+ var documentClientHeight = d ? d.clientHeight : null;
1247
+ var documentScrollHeight = d ? d.scrollHeight : null;
1248
+ var documentOffsetHeight = d ? d.offsetHeight : null;
1249
+ var height = Math.max(bodyClientHeight, bodyScrollHeight, bodyOffsetHeight, documentClientHeight, documentScrollHeight, documentOffsetHeight);
1250
+ // Check that width or height has changed from before, and also that width & height are not null values
1251
+ if ((data$a === null || width !== data$a.width || height !== data$a.height) && width !== null && height !== null) {
1252
+ data$a = { width: width, height: height };
1253
+ encode$4(8 /* Document */);
1254
+ }
1255
+ }
1256
+ function end() {
1257
+ reset$g();
1258
+ }
1259
+
1260
+ function encode$4 (type, timer, ts) {
1261
+ if (timer === void 0) { timer = null; }
1262
+ if (ts === void 0) { ts = null; }
1263
+ return __awaiter(this, void 0, void 0, function () {
1264
+ var eventTime, tokens, _a, d, _i, _b, r, b, _c, b_1, entry, values, _d, values_1, value, state, data, active, privacy, mangle, keys, _e, keys_1, key, size, factor, attr;
1265
+ return __generator(this, function (_f) {
1266
+ switch (_f.label) {
1267
+ case 0:
1268
+ eventTime = ts || time();
1269
+ tokens = [eventTime, type];
1270
+ _a = type;
1271
+ switch (_a) {
1272
+ case 8 /* Document */: return [3 /*break*/, 1];
1273
+ case 7 /* Region */: return [3 /*break*/, 2];
1274
+ case 37 /* Box */: return [3 /*break*/, 3];
1275
+ case 5 /* Discover */: return [3 /*break*/, 4];
1276
+ case 6 /* Mutation */: return [3 /*break*/, 4];
1277
+ }
1278
+ return [3 /*break*/, 11];
1279
+ case 1:
1280
+ d = data$a;
1281
+ tokens.push(d.width);
1282
+ tokens.push(d.height);
1283
+ track$7(type, d.width, d.height);
1284
+ queue(tokens);
1285
+ return [3 /*break*/, 11];
1286
+ case 2:
1287
+ for (_i = 0, _b = state$5; _i < _b.length; _i++) {
1288
+ r = _b[_i];
1289
+ tokens = [r.time, 7 /* Region */];
1290
+ tokens.push(r.data.id);
1291
+ tokens.push(r.data.state);
1292
+ tokens.push(r.data.name);
1293
+ queue(tokens);
1294
+ }
1295
+ reset$d();
1296
+ return [3 /*break*/, 11];
1297
+ case 3:
1298
+ b = data$9;
1299
+ for (_c = 0, b_1 = b; _c < b_1.length; _c++) {
1300
+ entry = b_1[_c];
1301
+ tokens.push(entry.id);
1302
+ tokens.push(entry.width);
1303
+ tokens.push(entry.height);
1304
+ }
1305
+ reset$f();
1306
+ queue(tokens);
1307
+ return [3 /*break*/, 11];
1308
+ case 4:
1309
+ // Check if we are operating within the context of the current page
1310
+ if (state$6(timer) === 2 /* Stop */) {
1311
+ return [3 /*break*/, 11];
1312
+ }
1313
+ values = updates$2();
1314
+ if (!(values.length > 0)) return [3 /*break*/, 10];
1315
+ _d = 0, values_1 = values;
1316
+ _f.label = 5;
1317
+ case 5:
1318
+ if (!(_d < values_1.length)) return [3 /*break*/, 9];
1319
+ value = values_1[_d];
1320
+ state = state$6(timer);
1321
+ if (!(state === 0 /* Wait */)) return [3 /*break*/, 7];
1322
+ return [4 /*yield*/, suspend$1(timer)];
1323
+ case 6:
1324
+ state = _f.sent();
1325
+ _f.label = 7;
1326
+ case 7:
1327
+ if (state === 2 /* Stop */) {
1328
+ return [3 /*break*/, 9];
1329
+ }
1330
+ data = value.data;
1331
+ active = value.metadata.active;
1332
+ privacy = value.metadata.privacy;
1333
+ mangle = shouldMangle(value);
1334
+ keys = active ? ["tag", "path", "attributes", "value"] : ["tag"];
1335
+ compute$5(value.id);
1336
+ for (_e = 0, keys_1 = keys; _e < keys_1.length; _e++) {
1337
+ key = keys_1[_e];
1338
+ if (data[key]) {
1339
+ switch (key) {
1340
+ case "tag":
1341
+ size = value.metadata.size;
1342
+ factor = mangle ? -1 : 1;
1343
+ tokens.push(value.id * factor);
1344
+ if (value.parent && active) {
1345
+ tokens.push(value.parent);
1346
+ }
1347
+ if (value.previous && active) {
1348
+ tokens.push(value.previous);
1349
+ }
1350
+ tokens.push(value.position ? data[key] + "~" + value.position : data[key]);
1351
+ if (size && size.length === 2) {
1352
+ tokens.push("" + "#" /* Box */ + str(size[0]) + "." + str(size[1]));
1353
+ }
1354
+ break;
1355
+ case "path":
1356
+ tokens.push(value.data.path + ">");
1357
+ break;
1358
+ case "attributes":
1359
+ for (attr in data[key]) {
1360
+ if (data[key][attr] !== undefined) {
1361
+ tokens.push(attribute(attr, data[key][attr], privacy));
1362
+ }
1363
+ }
1364
+ break;
1365
+ case "value":
1366
+ tokens.push(scrub(data[key], data.tag, privacy, mangle));
1367
+ break;
1368
+ }
1369
+ }
1370
+ }
1371
+ _f.label = 8;
1372
+ case 8:
1373
+ _d++;
1374
+ return [3 /*break*/, 5];
1375
+ case 9:
1376
+ if (type === 6 /* Mutation */) {
1377
+ activity(eventTime);
1378
+ }
1379
+ queue(tokenize(tokens), !config$1.lean);
1380
+ _f.label = 10;
1381
+ case 10: return [3 /*break*/, 11];
1382
+ case 11: return [2 /*return*/];
1383
+ }
1384
+ });
1385
+ });
1386
+ }
1387
+ function shouldMangle(value) {
1388
+ var privacy = value.metadata.privacy;
1389
+ return value.data.tag === "*T" /* TextTag */ && !(privacy === 0 /* None */ || privacy === 1 /* Sensitive */);
1390
+ }
1391
+ function str(input) {
1392
+ return input.toString(36);
1393
+ }
1394
+ function attribute(key, value, privacy) {
1395
+ return key + "=" + scrub(value, key, privacy);
1396
+ }
1397
+
1398
+ var data$9 = [];
1399
+ var enabled = false;
1400
+ var observer$2 = null;
1401
+ function start$q() {
1402
+ reset$f();
1403
+ observer$2 = null;
1404
+ enabled = window["ResizeObserver"] ? true : false;
1405
+ }
1406
+ function compute$5(id) {
1407
+ if (enabled === false) {
1408
+ return;
1409
+ }
1410
+ observer$2 = observer$2 === null ? new ResizeObserver(handler$4) : observer$2;
1411
+ if (observer$2) {
1412
+ var value = getValue(id);
1413
+ // If this is the first time computing size for this node, go ahead and wire up ResizeObserver
1414
+ // In all other cases, value.metadata.size will be null or an array with two elements [width, height]
1415
+ // And, in those cases, we will skip through the following section and not attach the observer
1416
+ if (value && value.metadata.size !== null && value.metadata.size.length === 0) {
1417
+ var node = getNode(id);
1418
+ if (node && node.nodeType === Node.ELEMENT_NODE) {
1419
+ var e = node;
1420
+ var r = e.getBoundingClientRect();
1421
+ value.metadata.size = [Math.floor(r.width * 100 /* BoxPrecision */), Math.floor(r.height * 100 /* BoxPrecision */)];
1422
+ observer$2.observe(e);
1423
+ }
1424
+ }
1425
+ }
1426
+ }
1427
+ function handler$4(entries) {
1428
+ window.requestAnimationFrame(function () {
1429
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
1430
+ var entry = entries_1[_i];
1431
+ var target = entry.target;
1432
+ var id = target ? getId(target) : null;
1433
+ if (id) {
1434
+ var v = getValue(id);
1435
+ var s = v.metadata.size;
1436
+ var b = entry.borderBoxSize;
1437
+ var w = null;
1438
+ var h = null;
1439
+ // Check if browser supports borderBoxSize property on ResizeObserverEntry object
1440
+ // Otherwise, fall back to using getBoundingClientRect() to be cross browser compatible
1441
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/borderBoxSize
1442
+ if (b && b.length > 0) {
1443
+ w = Math.floor(b[0].inlineSize * 100 /* BoxPrecision */);
1444
+ h = Math.floor(b[0].blockSize * 100 /* BoxPrecision */);
1445
+ }
1446
+ else {
1447
+ var r = target.getBoundingClientRect();
1448
+ w = Math.floor(r.width * 100 /* BoxPrecision */);
1449
+ h = Math.floor(r.height * 100 /* BoxPrecision */);
1450
+ }
1451
+ // Capture new width & height only if they are different from what we have in in-memory cache
1452
+ if (w !== s[0] && h !== s[1]) {
1453
+ s = [w, h];
1454
+ data$9.push({ id: id, width: w, height: h });
1455
+ }
1456
+ }
1457
+ }
1458
+ // Schedule encode only when we have at least one valid data entry
1459
+ if (data$9.length > 0) {
1460
+ encode$4(37 /* Box */);
1461
+ }
1462
+ });
1463
+ }
1464
+ function reset$f() {
1465
+ data$9 = [];
1466
+ }
1467
+ function stop$o() {
1468
+ reset$f();
1469
+ if (observer$2) {
1470
+ observer$2.disconnect();
1471
+ observer$2 = null;
1472
+ }
1473
+ enabled = false;
1474
+ }
1475
+
1476
+ var history$4 = {};
1477
+ var data$8;
1478
+ function start$p() {
1479
+ bind(window, "error", handler$3);
1480
+ history$4 = {};
1481
+ }
1482
+ function handler$3(error) {
1483
+ var e = error["error"] || error;
1484
+ // While rare, it's possible for code to fail repeatedly during the lifetime of the same page
1485
+ // In those cases, we only want to log the failure first few times and not spam logs with redundant information.
1486
+ if (!(e.message in history$4)) {
1487
+ history$4[e.message] = 0;
1488
+ }
1489
+ if (history$4[e.message]++ >= 5 /* ScriptErrorLimit */) {
1490
+ return true;
1491
+ }
1492
+ // Send back information only if the handled error has valid information
1493
+ if (e && e.message) {
1494
+ data$8 = {
1495
+ message: e.message,
1496
+ line: error["lineno"],
1497
+ column: error["colno"],
1498
+ stack: e.stack,
1499
+ source: error["filename"]
1500
+ };
1501
+ // In certain cases, ResizeObserver could lead to flood of benign errors - especially when video element is involved.
1502
+ // Reference Chromium issue: https://bugs.chromium.org/p/chromium/issues/detail?id=809574
1503
+ // Even though it doesn't impact user experience, or show up in console, it can still flood error reporting through on error
1504
+ // To mitigate that, we turn off Clarity's ResizeObserver on getting the first instance of this error
1505
+ if (e.message.indexOf("ResizeObserver" /* ResizeObserver */) >= 0) {
1506
+ stop$o();
1507
+ return false;
1508
+ }
1509
+ encode$3(31 /* ScriptError */);
1510
+ }
1511
+ return true;
1512
+ }
1513
+
1514
+ function encode$3 (type) {
1515
+ return __awaiter(this, void 0, void 0, function () {
1516
+ var tokens, imageTarget;
1517
+ return __generator(this, function (_a) {
1518
+ tokens = [time(), type];
1519
+ switch (type) {
1520
+ case 31 /* ScriptError */:
1521
+ tokens.push(data$8.message);
1522
+ tokens.push(data$8.line);
1523
+ tokens.push(data$8.column);
1524
+ tokens.push(data$8.stack);
1525
+ tokens.push(data$8.source);
1526
+ queue(tokens);
1527
+ break;
1528
+ case 32 /* ImageError */:
1529
+ if (data$b) {
1530
+ imageTarget = metadata(data$b.target, type);
1531
+ tokens.push(data$b.source);
1532
+ tokens.push(imageTarget.id);
1533
+ queue(tokens);
1534
+ }
1535
+ break;
1536
+ case 33 /* Log */:
1537
+ if (data$7) {
1538
+ tokens.push(data$7.code);
1539
+ tokens.push(data$7.name);
1540
+ tokens.push(data$7.message);
1541
+ tokens.push(data$7.stack);
1542
+ tokens.push(data$7.severity);
1543
+ queue(tokens, false);
1544
+ }
1545
+ break;
1546
+ }
1547
+ return [2 /*return*/];
1548
+ });
1549
+ });
1550
+ }
1551
+
1552
+ var history$3 = {};
1553
+ var data$7;
1554
+ function start$o() {
1555
+ history$3 = {};
1556
+ bind(document, "securitypolicyviolation", csp);
1557
+ }
1558
+ function log(code, severity, name, message, stack) {
1559
+ if (name === void 0) { name = null; }
1560
+ if (message === void 0) { message = null; }
1561
+ if (stack === void 0) { stack = null; }
1562
+ var key = name ? name + "|" + message : "";
1563
+ // While rare, it's possible for code to fail repeatedly during the lifetime of the same page
1564
+ // In those cases, we only want to log the failure once and not spam logs with redundant information.
1565
+ if (code in history$3 && history$3[code].indexOf(key) >= 0) {
1566
+ return;
1567
+ }
1568
+ data$7 = { code: code, name: name, message: message, stack: stack, severity: severity };
1569
+ // Maintain history of errors in memory to avoid sending redundant information
1570
+ if (code in history$3) {
1571
+ history$3[code].push(key);
1572
+ }
1573
+ else {
1574
+ history$3[code] = [key];
1575
+ }
1576
+ encode$3(33 /* Log */);
1577
+ }
1578
+ function csp(e) {
1579
+ var upload = config$1.upload;
1580
+ var parts = upload ? upload.substr(0, upload.indexOf("/", "https://" /* HTTPS */.length)).split("." /* Dot */) : []; // Look for first "/" starting after initial "https://" string
1581
+ var domain = parts.length >= 2 ? parts.splice(-2).join("." /* Dot */) : null;
1582
+ // Capture content security policy violation only if disposition value is not explicitly set to "report"
1583
+ if (domain && e.blockedURI && e.blockedURI.indexOf(domain) >= 0 && e["disposition"] !== "report" /* Report */) {
1584
+ log(7 /* ContentSecurityPolicy */, 1 /* Warning */, e.blockedURI);
1585
+ }
1586
+ }
1587
+ function stop$n() {
1588
+ history$3 = {};
1589
+ }
1590
+
1591
+ var formatRegex = /1/g;
1592
+ var digitsRegex$1 = /[^0-9\.]/g;
1593
+ var digitsWithCommaRegex = /[^0-9\.,]/g;
1594
+ var regexCache = {};
1595
+ function regions$1(root, value) {
1596
+ var _loop_1 = function (v) {
1597
+ var regionId = v[0], selector = v[1], filter = v[2], match = v[3];
1598
+ var valid = true;
1599
+ switch (filter) {
1600
+ case 0 /* Url */:
1601
+ valid = match && !!top.location.href.match(regex(match));
1602
+ break;
1603
+ case 1 /* Javascript */:
1604
+ valid = match && !!evaluate(match);
1605
+ break;
1606
+ }
1607
+ if (valid) {
1608
+ root.querySelectorAll(selector).forEach(function (e) { return observe$9(e, regionId.toString()); });
1609
+ }
1610
+ };
1611
+ for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
1612
+ var v = value_1[_i];
1613
+ _loop_1(v);
1614
+ }
1615
+ }
1616
+ function metrics(root, value) {
1617
+ var _loop_2 = function (v) {
1618
+ var metricId = v[0], source = v[1], match = v[2], scale = v[3];
1619
+ if (match) {
1620
+ switch (source) {
1621
+ case 0 /* Text */:
1622
+ root.querySelectorAll(match).forEach(function (e) { max(metricId, num$1(e.innerText, scale)); });
1623
+ break;
1624
+ case 2 /* Attribute */:
1625
+ root.querySelectorAll("[" + match + "]").forEach(function (e) { max(metricId, num$1(e.getAttribute(match), scale, false)); });
1626
+ break;
1627
+ case 1 /* Javascript */:
1628
+ max(metricId, evaluate(match, "number" /* Number */));
1629
+ break;
1630
+ }
1631
+ }
1632
+ };
1633
+ for (var _i = 0, value_2 = value; _i < value_2.length; _i++) {
1634
+ var v = value_2[_i];
1635
+ _loop_2(v);
1636
+ }
1637
+ }
1638
+ function regex(match) {
1639
+ regexCache[match] = match in regexCache ? regexCache[match] : new RegExp(match);
1640
+ return regexCache[match];
1641
+ }
1642
+ // The function below takes in a variable name in following format: "a.b.c" and safely evaluates its value in javascript context
1643
+ // For instance, for a.b.c, it will first check window["a"]. If it exists, it will recursively look at: window["a"]["b"] and finally,
1644
+ // return the value for window["a"]["b"]["c"].
1645
+ function evaluate(variable, type, base) {
1646
+ if (type === void 0) { type = null; }
1647
+ if (base === void 0) { base = window; }
1648
+ var parts = variable.split("." /* Dot */);
1649
+ var first = parts.shift();
1650
+ if (base && base[first]) {
1651
+ if (parts.length > 0) {
1652
+ return evaluate(parts.join("." /* Dot */), type, base[first]);
1653
+ }
1654
+ var output = type === null || type === typeof base[first] ? base[first] : null;
1655
+ return output;
1656
+ }
1657
+ return null;
1658
+ }
1659
+ function num$1(text, scale, localize) {
1660
+ if (localize === void 0) { localize = true; }
1661
+ try {
1662
+ scale = scale || 1;
1663
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
1664
+ var lang = document.documentElement.lang;
1665
+ if (Intl && Intl.NumberFormat && lang && localize) {
1666
+ text = text.replace(digitsWithCommaRegex, "" /* Empty */);
1667
+ // Infer current group and decimal separator from current locale
1668
+ var group = Intl.NumberFormat(lang).format(11111).replace(formatRegex, "" /* Empty */);
1669
+ var decimal = Intl.NumberFormat(lang).format(1.1).replace(formatRegex, "" /* Empty */);
1670
+ // Parse number using inferred group and decimal separators
1671
+ return Math.round(parseFloat(text
1672
+ .replace(new RegExp('\\' + group, 'g'), "" /* Empty */)
1673
+ .replace(new RegExp('\\' + decimal), "." /* Dot */)) * scale);
1674
+ }
1675
+ // Fallback to en locale
1676
+ return Math.round(parseFloat(text.replace(digitsRegex$1, "" /* Empty */)) * scale);
1677
+ }
1678
+ catch (_a) {
1679
+ return null;
1680
+ }
1681
+ }
1682
+
1683
+ function selector (tag, prefix, attributes, position) {
1684
+ var suffix = position ? ":nth-of-type(" + position + ")" : "" /* Empty */;
1685
+ switch (tag) {
1686
+ case "STYLE":
1687
+ case "TITLE":
1688
+ case "LINK":
1689
+ case "META":
1690
+ case "*T" /* TextTag */:
1691
+ case "*D" /* DocumentTag */:
1692
+ return "" /* Empty */;
1693
+ case "HTML":
1694
+ return "HTML" /* HTML */;
1695
+ default:
1696
+ if (prefix === null) {
1697
+ return "" /* Empty */;
1698
+ }
1699
+ tag = tag.indexOf("svg:" /* SvgPrefix */) === 0 ? tag.substr("svg:" /* SvgPrefix */.length) : tag;
1700
+ var selector = "" + prefix + tag + suffix;
1701
+ if ("class" /* Class */ in attributes && attributes["class" /* Class */].length > 0) {
1702
+ selector = "" + prefix + tag + "." + attributes.class.trim().split(/\s+/).join(".") + suffix;
1703
+ }
1704
+ return selector;
1705
+ }
1706
+ }
1707
+
1708
+ var index = 1;
1709
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#%3Cinput%3E_types
1710
+ var DISALLOWED_TYPES = ["password", "hidden", "email", "tel"];
1711
+ var DISALLOWED_NAMES = ["addr", "cell", "code", "dob", "email", "mob", "name", "phone", "secret", "social", "ssn", "tel", "zip", "pass"];
1712
+ var DISALLOWED_MATCH = ["address", "password", "contact"];
1713
+ var nodes = [];
1714
+ var values = [];
1715
+ var changes = [];
1716
+ var updateMap = [];
1717
+ var selectorMap = [];
1718
+ // The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced
1719
+ var idMap = null; // Maps node => id.
1720
+ var iframeMap = null; // Maps iframe's contentDocument => parent iframe element
1721
+ var privacyMap = null; // Maps node => Privacy (enum)
1722
+ var urlMap = {};
1723
+ function start$n() {
1724
+ reset$e();
1725
+ parse(document);
1726
+ }
1727
+ function stop$m() {
1728
+ reset$e();
1729
+ }
1730
+ function reset$e() {
1731
+ index = 1;
1732
+ nodes = [];
1733
+ values = [];
1734
+ updateMap = [];
1735
+ changes = [];
1736
+ selectorMap = [];
1737
+ urlMap = {};
1738
+ idMap = new WeakMap();
1739
+ iframeMap = new WeakMap();
1740
+ privacyMap = new WeakMap();
1741
+ if ("__CLARITY_DEVTOOLS_HOOK__" /* DevHook */ in window) {
1742
+ window["__CLARITY_DEVTOOLS_HOOK__" /* DevHook */] = { get: get, getNode: getNode, history: history$2 };
1743
+ }
1744
+ }
1745
+ // We parse new root nodes for any regions or masked nodes in the beginning (document) and
1746
+ // later whenever there are new additions or modifications to DOM (mutations)
1747
+ function parse(root) {
1748
+ // Wrap selectors in a try / catch block.
1749
+ // It's possible for script to receive invalid selectors, e.g. "'#id'" with extra quotes, and cause the code below to fail
1750
+ try {
1751
+ // Since mutations may happen on leaf nodes too, e.g. text nodes, which may not support all selector APIs.
1752
+ // We ensure that the root note supports querySelectorAll API before executing the code below to identify new regions.
1753
+ if ("querySelectorAll" in root) {
1754
+ regions$1(root, config$1.regions);
1755
+ metrics(root, config$1.metrics);
1756
+ config$1.mask.forEach(function (x) { return root.querySelectorAll(x).forEach(function (e) { return privacyMap.set(e, 3 /* TextImage */); }); }); // Masked Elements
1757
+ config$1.unmask.forEach(function (x) { return root.querySelectorAll(x).forEach(function (e) { return privacyMap.set(e, 0 /* None */); }); }); // Unmasked Elements
1758
+ }
1759
+ }
1760
+ catch (e) {
1761
+ log(5 /* Selector */, 1 /* Warning */, e ? e.name : null);
1762
+ }
1763
+ }
1764
+ function getId(node, autogen) {
1765
+ if (autogen === void 0) { autogen = false; }
1766
+ if (node === null) {
1767
+ return null;
1768
+ }
1769
+ var id = idMap.get(node);
1770
+ if (!id && autogen) {
1771
+ id = index++;
1772
+ idMap.set(node, id);
1773
+ }
1774
+ return id ? id : null;
1775
+ }
1776
+ function add(node, parent, data, source) {
1777
+ var id = getId(node, true);
1778
+ var parentId = parent ? getId(parent) : null;
1779
+ var previousId = getPreviousId(node);
1780
+ var privacy = config$1.content ? 1 /* Sensitive */ : 2 /* Text */;
1781
+ var parentValue = null;
1782
+ var parentTag = "" /* Empty */;
1783
+ var regionId = exists(node) ? id : null;
1784
+ if (parentId >= 0 && values[parentId]) {
1785
+ parentValue = values[parentId];
1786
+ parentTag = parentValue.data.tag;
1787
+ parentValue.children.push(id);
1788
+ regionId = regionId === null ? parentValue.region : regionId;
1789
+ privacy = parentValue.metadata.privacy;
1790
+ }
1791
+ // Check to see if this particular node should be masked or not
1792
+ privacy = getPrivacy(node, data, parentTag, privacy);
1793
+ // If there's an explicit region attribute set on the element, use it to mark a region on the page
1794
+ if (data.attributes && "data-clarity-region" /* RegionData */ in data.attributes) {
1795
+ observe$9(node, data.attributes["data-clarity-region" /* RegionData */]);
1796
+ regionId = id;
1797
+ }
1798
+ nodes[id] = node;
1799
+ values[id] = {
1800
+ id: id,
1801
+ parent: parentId,
1802
+ previous: previousId,
1803
+ children: [],
1804
+ position: null,
1805
+ data: data,
1806
+ selector: "" /* Empty */,
1807
+ region: regionId,
1808
+ metadata: { active: true, privacy: privacy, size: null }
1809
+ };
1810
+ updateSelector(values[id]);
1811
+ size(values[id], parentValue);
1812
+ metadata$1(data.tag, id, parentId);
1813
+ track$4(id, source);
1814
+ }
1815
+ function update(node, parent, data, source) {
1816
+ var id = getId(node);
1817
+ var parentId = parent ? getId(parent) : null;
1818
+ var previousId = getPreviousId(node);
1819
+ var changed = false;
1820
+ var parentChanged = false;
1821
+ if (id in values) {
1822
+ var value = values[id];
1823
+ value.metadata.active = true;
1824
+ // Handle case where internal ordering may have changed
1825
+ if (value.previous !== previousId) {
1826
+ changed = true;
1827
+ value.previous = previousId;
1828
+ }
1829
+ // Handle case where parent might have been updated
1830
+ if (value.parent !== parentId) {
1831
+ changed = true;
1832
+ var oldParentId = value.parent;
1833
+ value.parent = parentId;
1834
+ // Move this node to the right location under new parent
1835
+ if (parentId !== null && parentId >= 0) {
1836
+ var childIndex = previousId === null ? 0 : values[parentId].children.indexOf(previousId) + 1;
1837
+ values[parentId].children.splice(childIndex, 0, id);
1838
+ // Update region after the move
1839
+ value.region = exists(node) ? id : values[parentId].region;
1840
+ }
1841
+ else {
1842
+ // Mark this element as deleted if the parent has been updated to null
1843
+ remove(id, source);
1844
+ }
1845
+ // Remove reference to this node from the old parent
1846
+ if (oldParentId !== null && oldParentId >= 0) {
1847
+ var nodeIndex = values[oldParentId].children.indexOf(id);
1848
+ if (nodeIndex >= 0) {
1849
+ values[oldParentId].children.splice(nodeIndex, 1);
1850
+ }
1851
+ }
1852
+ parentChanged = true;
1853
+ }
1854
+ // Update data
1855
+ for (var key in data) {
1856
+ if (diff(value["data"], data, key)) {
1857
+ changed = true;
1858
+ value["data"][key] = data[key];
1859
+ }
1860
+ }
1861
+ // Update selector
1862
+ updateSelector(value);
1863
+ metadata$1(data.tag, id, parentId);
1864
+ track$4(id, source, changed, parentChanged);
1865
+ }
1866
+ }
1867
+ function sameorigin(node) {
1868
+ var output = false;
1869
+ if (node.nodeType === Node.ELEMENT_NODE && node.tagName === "IFRAME" /* IFrameTag */) {
1870
+ var frame = node;
1871
+ // To determine if the iframe is same-origin or not, we try accessing it's contentDocument.
1872
+ // If the browser throws an exception, we assume it's cross-origin and move on.
1873
+ // However, if we do a get a valid document object back, we assume the contents are accessible and iframe is same-origin.
1874
+ try {
1875
+ var doc = frame.contentDocument;
1876
+ if (doc) {
1877
+ iframeMap.set(frame.contentDocument, frame);
1878
+ output = true;
1879
+ }
1880
+ }
1881
+ catch ( /* do nothing */_a) { /* do nothing */ }
1882
+ }
1883
+ return output;
1884
+ }
1885
+ function iframe(node) {
1886
+ var doc = node.nodeType === Node.DOCUMENT_NODE ? node : null;
1887
+ return doc && iframeMap.has(doc) ? iframeMap.get(doc) : null;
1888
+ }
1889
+ function getPrivacy(node, data, parentTag, privacy) {
1890
+ var attributes = data.attributes;
1891
+ var tag = data.tag.toUpperCase();
1892
+ // If this node was explicitly configured to contain sensitive content, use that information and return the value
1893
+ if (privacyMap.has(node)) {
1894
+ return privacyMap.get(node);
1895
+ }
1896
+ // Do not proceed if attributes are missing for the node
1897
+ if (attributes === null || attributes === undefined) {
1898
+ return privacy;
1899
+ }
1900
+ // Look up for sensitive fields
1901
+ if ("class" /* Class */ in attributes && privacy === 1 /* Sensitive */) {
1902
+ for (var _i = 0, DISALLOWED_MATCH_1 = DISALLOWED_MATCH; _i < DISALLOWED_MATCH_1.length; _i++) {
1903
+ var match = DISALLOWED_MATCH_1[_i];
1904
+ if (attributes["class" /* Class */].indexOf(match) >= 0) {
1905
+ privacy = 2 /* Text */;
1906
+ break;
1907
+ }
1908
+ }
1909
+ }
1910
+ // Check for disallowed list of fields (e.g. address, phone, etc.) only if the input node is not already masked
1911
+ if (tag === "INPUT" /* InputTag */) {
1912
+ if (privacy === 0 /* None */) {
1913
+ var field = "" /* Empty */;
1914
+ // Be aggressive in looking up any attribute (id, class, name, etc.) for disallowed names
1915
+ for (var _a = 0, _b = Object.keys(attributes); _a < _b.length; _a++) {
1916
+ var attribute = _b[_a];
1917
+ field += attributes[attribute].toLowerCase();
1918
+ }
1919
+ for (var _c = 0, DISALLOWED_NAMES_1 = DISALLOWED_NAMES; _c < DISALLOWED_NAMES_1.length; _c++) {
1920
+ var name_1 = DISALLOWED_NAMES_1[_c];
1921
+ if (field.indexOf(name_1) >= 0) {
1922
+ privacy = 2 /* Text */;
1923
+ break;
1924
+ }
1925
+ }
1926
+ }
1927
+ else if (privacy === 1 /* Sensitive */) {
1928
+ // Mask all input fields with an exception of type=submit; since they do not accept user input
1929
+ privacy = attributes && attributes["type" /* Type */] === "submit" /* Submit */ ? 0 /* None */ : 2 /* Text */;
1930
+ }
1931
+ }
1932
+ // Check for disallowed list of types (e.g. password, email, etc.) and set the masked property appropriately
1933
+ if ("type" /* Type */ in attributes && DISALLOWED_TYPES.indexOf(attributes["type" /* Type */]) >= 0) {
1934
+ privacy = 2 /* Text */;
1935
+ }
1936
+ // Following two conditions supersede any of the above. If there are explicit instructions to mask / unmask a field, we honor that.
1937
+ if ("data-clarity-mask" /* MaskData */ in attributes) {
1938
+ privacy = 3 /* TextImage */;
1939
+ }
1940
+ if ("data-clarity-unmask" /* UnmaskData */ in attributes) {
1941
+ privacy = 0 /* None */;
1942
+ }
1943
+ // If it's a text node belonging to a STYLE or TITLE tag; then reset the privacy setting to ensure we capture the content
1944
+ var cTag = tag === "*T" /* TextTag */ ? parentTag : tag;
1945
+ if (cTag === "STYLE" /* StyleTag */ || cTag === "TITLE" /* TitleTag */) {
1946
+ privacy = 0 /* None */;
1947
+ }
1948
+ return privacy;
1949
+ }
1950
+ function diff(a, b, field) {
1951
+ if (typeof a[field] === "object" && typeof b[field] === "object") {
1952
+ for (var key in a[field]) {
1953
+ if (a[field][key] !== b[field][key]) {
1954
+ return true;
1955
+ }
1956
+ }
1957
+ for (var key in b[field]) {
1958
+ if (b[field][key] !== a[field][key]) {
1959
+ return true;
1960
+ }
1961
+ }
1962
+ return false;
1963
+ }
1964
+ return a[field] !== b[field];
1965
+ }
1966
+ function position(parent, child) {
1967
+ var tag = child.data.tag;
1968
+ var hasClassName = child.data.attributes && !("class" /* Class */ in child.data.attributes);
1969
+ // Find relative position of the element to generate :nth-of-type selector
1970
+ // We restrict relative positioning to two cases:
1971
+ // a) For specific whitelist of tags
1972
+ // b) And, for remaining tags, only if they don't have a valid class name
1973
+ if (parent && (["DIV", "TR", "P", "LI", "UL", "A", "BUTTON"].indexOf(tag) >= 0 || hasClassName)) {
1974
+ child.position = 1;
1975
+ var idx = parent ? parent.children.indexOf(child.id) : -1;
1976
+ while (idx-- > 0) {
1977
+ var sibling = values[parent.children[idx]];
1978
+ if (child.data.tag === sibling.data.tag) {
1979
+ child.position = sibling.position + 1;
1980
+ break;
1981
+ }
1982
+ }
1983
+ }
1984
+ return child.position;
1985
+ }
1986
+ function updateSelector(value) {
1987
+ var parent = value.parent && value.parent in values ? values[value.parent] : null;
1988
+ var prefix = parent ? parent.selector + ">" : null;
1989
+ var ex = value.selector;
1990
+ var current = selector(value.data.tag, prefix, value.data.attributes, position(parent, value));
1991
+ if (current !== ex && selectorMap.indexOf(value.id) === -1) {
1992
+ selectorMap.push(value.id);
1993
+ }
1994
+ value.selector = current;
1995
+ }
1996
+ function getNode(id) {
1997
+ if (id in nodes) {
1998
+ return nodes[id];
1999
+ }
2000
+ return null;
2001
+ }
2002
+ function getMatch(url) {
2003
+ if (url in urlMap) {
2004
+ return getNode(urlMap[url]);
2005
+ }
2006
+ return null;
2007
+ }
2008
+ function getValue(id) {
2009
+ if (id in values) {
2010
+ return values[id];
2011
+ }
2012
+ return null;
2013
+ }
2014
+ function get(node) {
2015
+ var id = getId(node);
2016
+ return id in values ? values[id] : null;
2017
+ }
2018
+ function has(node) {
2019
+ return getId(node) in nodes;
2020
+ }
2021
+ function updates$2() {
2022
+ var output = [];
2023
+ for (var _i = 0, updateMap_1 = updateMap; _i < updateMap_1.length; _i++) {
2024
+ var id = updateMap_1[_i];
2025
+ if (id in values) {
2026
+ var v = values[id];
2027
+ var p = v.parent;
2028
+ v.data.path = p === null || updateMap.indexOf(p) >= 0 || v.selector.length === 0 ? null : values[p].selector;
2029
+ output.push(values[id]);
2030
+ }
2031
+ }
2032
+ updateMap = [];
2033
+ return output;
2034
+ }
2035
+ function remove(id, source) {
2036
+ if (id in values) {
2037
+ var value = values[id];
2038
+ value.metadata.active = false;
2039
+ value.parent = null;
2040
+ track$4(id, source);
2041
+ }
2042
+ }
2043
+ function size(value, parent) {
2044
+ var data = value.data;
2045
+ var tag = data.tag;
2046
+ // If this element is a text node, is masked, and longer than configured length, then track box model for the parent element
2047
+ var isLongText = tag === "*T" /* TextTag */ && data.value && data.value.length > 15 /* ResizeObserverThreshold */;
2048
+ var isMasked = value.metadata.privacy === 2 /* Text */ || value.metadata.privacy === 3 /* TextImage */;
2049
+ if (isLongText && isMasked && parent && parent.metadata.size === null) {
2050
+ parent.metadata.size = [];
2051
+ }
2052
+ // If this element is a image node, and is masked, then track box model for the current element
2053
+ if (data.tag === "IMG" /* ImageTag */ && value.metadata.privacy === 3 /* TextImage */) {
2054
+ value.metadata.size = [];
2055
+ }
2056
+ }
2057
+ function metadata$1(tag, id, parentId) {
2058
+ if (id !== null && parentId !== null) {
2059
+ var value = values[id];
2060
+ var attributes = "attributes" in value.data ? value.data.attributes : {};
2061
+ switch (tag) {
2062
+ case "VIDEO":
2063
+ case "AUDIO":
2064
+ case "LINK":
2065
+ // Track mapping between URL and corresponding nodes
2066
+ if ("href" /* Href */ in attributes && attributes["href" /* Href */].length > 0) {
2067
+ urlMap[getFullUrl(attributes["href" /* Href */])] = id;
2068
+ }
2069
+ if ("src" /* Src */ in attributes && attributes["src" /* Src */].length > 0) {
2070
+ if (attributes["src" /* Src */].indexOf("data:" /* DataPrefix */) !== 0) {
2071
+ urlMap[getFullUrl(attributes["src" /* Src */])] = id;
2072
+ }
2073
+ }
2074
+ if ("srcset" /* Srcset */ in attributes && attributes["srcset" /* Srcset */].length > 0) {
2075
+ var srcset = attributes["srcset" /* Srcset */];
2076
+ var urls = srcset.split(",");
2077
+ for (var _i = 0, urls_1 = urls; _i < urls_1.length; _i++) {
2078
+ var u = urls_1[_i];
2079
+ var parts = u.trim().split(" ");
2080
+ if (parts.length === 2 && parts[0].length > 0) {
2081
+ urlMap[getFullUrl(parts[0])] = id;
2082
+ }
2083
+ }
2084
+ }
2085
+ break;
2086
+ }
2087
+ }
2088
+ }
2089
+ function getFullUrl(relative) {
2090
+ var a = document.createElement("a");
2091
+ a.href = relative;
2092
+ return a.href;
2093
+ }
2094
+ function getPreviousId(node) {
2095
+ var id = null;
2096
+ // Some nodes may not have an ID by design since Clarity skips over tags like SCRIPT, NOSCRIPT, META, COMMENTS, etc..
2097
+ // In that case, we keep going back and check for their sibling until we find a sibling with ID or no more sibling nodes are left.
2098
+ while (id === null && node.previousSibling) {
2099
+ id = getId(node.previousSibling);
2100
+ node = node.previousSibling;
2101
+ }
2102
+ return id;
2103
+ }
2104
+ function copy(input) {
2105
+ return JSON.parse(JSON.stringify(input));
2106
+ }
2107
+ function track$4(id, source, changed, parentChanged) {
2108
+ if (changed === void 0) { changed = true; }
2109
+ if (parentChanged === void 0) { parentChanged = false; }
2110
+ // Keep track of the order in which mutations happened, they may not be sequential
2111
+ // Edge case: If an element is added later on, and pre-discovered element is moved as a child.
2112
+ // In that case, we need to reorder the pre-discovered element in the update list to keep visualization consistent.
2113
+ var uIndex = updateMap.indexOf(id);
2114
+ if (uIndex >= 0 && source === 1 /* ChildListAdd */ && parentChanged) {
2115
+ updateMap.splice(uIndex, 1);
2116
+ updateMap.push(id);
2117
+ }
2118
+ else if (uIndex === -1 && changed) {
2119
+ updateMap.push(id);
2120
+ }
2121
+ if ("__CLARITY_DEVTOOLS_HOOK__" /* DevHook */ in window) {
2122
+ var value = copy([values[id]])[0];
2123
+ var change = { time: time(), source: source, value: value };
2124
+ if (!(id in changes)) {
2125
+ changes[id] = [];
2126
+ }
2127
+ changes[id].push(change);
2128
+ }
2129
+ }
2130
+ function history$2(id) {
2131
+ if (id in changes) {
2132
+ return changes[id];
2133
+ }
2134
+ return [];
2135
+ }
2136
+
2137
+ var dom = /*#__PURE__*/Object.freeze({
2138
+ __proto__: null,
2139
+ start: start$n,
2140
+ stop: stop$m,
2141
+ parse: parse,
2142
+ getId: getId,
2143
+ add: add,
2144
+ update: update,
2145
+ sameorigin: sameorigin,
2146
+ iframe: iframe,
2147
+ getNode: getNode,
2148
+ getMatch: getMatch,
2149
+ getValue: getValue,
2150
+ get: get,
2151
+ has: has,
2152
+ updates: updates$2
2153
+ });
2154
+
2155
+ var state$5 = [];
2156
+ var regionMap = null; // Maps region nodes => region name
2157
+ var regions = {};
2158
+ var queue$2 = [];
2159
+ var watch = false;
2160
+ var observer$1 = null;
2161
+ function start$m() {
2162
+ reset$d();
2163
+ observer$1 = null;
2164
+ regionMap = new WeakMap();
2165
+ regions = {};
2166
+ queue$2 = [];
2167
+ watch = window["IntersectionObserver"] ? true : false;
2168
+ }
2169
+ function observe$9(node, name) {
2170
+ if (regionMap.has(node) === false) {
2171
+ regionMap.set(node, name);
2172
+ observer$1 = observer$1 === null && watch ? new IntersectionObserver(handler$2, {
2173
+ // Get notified as intersection continues to change
2174
+ // This allows us to process regions that get partially hidden during the lifetime of the page
2175
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#creating_an_intersection_observer
2176
+ // By default, intersection observers only fire an event when even a single pixel is visible and not thereafter.
2177
+ threshold: [0, 0.2, 0.4, 0.6, 0.8, 1]
2178
+ }) : observer$1;
2179
+ if (observer$1 && node && node.nodeType === Node.ELEMENT_NODE) {
2180
+ observer$1.observe(node);
2181
+ }
2182
+ }
2183
+ }
2184
+ function exists(node) {
2185
+ // Check if regionMap is not null before looking up a node
2186
+ // Since, dom module stops after region module, it's possible that we may set regionMap to be null
2187
+ // and still attempt to call exists on a late coming DOM mutation (or addition), effectively causing a script error
2188
+ return regionMap && regionMap.has(node);
2189
+ }
2190
+ function track$3(id, event) {
2191
+ var node = getNode(id);
2192
+ var data = id in regions ? regions[id] : { id: id, state: 0 /* Rendered */, name: regionMap.get(node) };
2193
+ // Determine the interaction state based on incoming event
2194
+ var interactionState = 0 /* Rendered */;
2195
+ switch (event) {
2196
+ case 9 /* Click */:
2197
+ interactionState = 20 /* Clicked */;
2198
+ break;
2199
+ case 27 /* Input */:
2200
+ interactionState = 30 /* Input */;
2201
+ break;
2202
+ }
2203
+ // Process updates to this region, if applicable
2204
+ process$6(node, data, interactionState);
2205
+ }
2206
+ function compute$4() {
2207
+ // Process any regions where we couldn't resolve an "id" for at the time of last intersection observer event
2208
+ // This could happen in cases where elements are not yet processed by Clarity's virtual DOM but browser reports a change, regardless.
2209
+ // For those cases we add them to the queue and re-process them below
2210
+ var q = [];
2211
+ for (var _i = 0, queue_1 = queue$2; _i < queue_1.length; _i++) {
2212
+ var r = queue_1[_i];
2213
+ var id = getId(r.node);
2214
+ if (!(id in regions)) {
2215
+ if (id) {
2216
+ r.data.id = id;
2217
+ regions[id] = r.data;
2218
+ state$5.push(clone(r.data));
2219
+ }
2220
+ else {
2221
+ q.push(r);
2222
+ }
2223
+ }
2224
+ }
2225
+ queue$2 = q;
2226
+ // Schedule encode only when we have at least one valid data entry
2227
+ if (state$5.length > 0) {
2228
+ encode$4(7 /* Region */);
2229
+ }
2230
+ }
2231
+ function handler$2(entries) {
2232
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
2233
+ var entry = entries_1[_i];
2234
+ var target = entry.target;
2235
+ var rect = entry.boundingClientRect;
2236
+ var overlap = entry.intersectionRect;
2237
+ var viewport = entry.rootBounds;
2238
+ // Only capture regions that have non-zero width or height to avoid tracking and sending regions
2239
+ // that cannot ever be seen by the user. In some cases, websites will have a multiple copy of the same region
2240
+ // like search box - one for desktop, and another for mobile. In those cases, CSS media queries determine which one should be visible.
2241
+ // Also, if these regions ever become non-zero width or height (through AJAX, user action or orientation change) - we will automatically start monitoring them from that point onwards
2242
+ if (regionMap.has(target) && rect.width + rect.height > 0 && viewport.width > 0 && viewport.height > 0) {
2243
+ var id = target ? getId(target) : null;
2244
+ var data = id in regions ? regions[id] : { id: id, name: regionMap.get(target), state: 0 /* Rendered */ };
2245
+ // For regions that have relatively smaller area, we look at intersection ratio and see the overlap relative to element's area
2246
+ // However, for larger regions, area of regions could be bigger than viewport and therefore comparison is relative to visible area
2247
+ var viewportRatio = overlap ? (overlap.width * overlap.height * 1.0) / (viewport.width * viewport.height) : 0;
2248
+ var visible = viewportRatio > 0.25 /* ViewportIntersectionRatio */ || entry.intersectionRatio > 0.8 /* IntersectionRatio */;
2249
+ // Process updates to this region, if applicable
2250
+ process$6(target, data, visible ? 10 /* Visible */ : 0 /* Rendered */);
2251
+ // Stop observing this element now that we have already received visibility signal
2252
+ if (data.state >= 10 /* Visible */ && observer$1) {
2253
+ observer$1.unobserve(target);
2254
+ }
2255
+ }
2256
+ }
2257
+ if (state$5.length > 0) {
2258
+ encode$4(7 /* Region */);
2259
+ }
2260
+ }
2261
+ function process$6(n, d, s) {
2262
+ // Check if received a state that supersedes existing state
2263
+ var updated = s > d.state;
2264
+ d.state = updated ? s : d.state;
2265
+ // If the corresponding node is already discovered, update the internal state
2266
+ // Otherwise, track it in a queue to reprocess later.
2267
+ if (d.id) {
2268
+ if ((d.id in regions && updated) || !(d.id in regions)) {
2269
+ regions[d.id] = d;
2270
+ state$5.push(clone(d));
2271
+ }
2272
+ }
2273
+ else {
2274
+ queue$2.push({ node: n, data: d });
2275
+ }
2276
+ }
2277
+ function clone(r) {
2278
+ return { time: time(), data: { id: r.id, state: r.state, name: r.name } };
2279
+ }
2280
+ function reset$d() {
2281
+ state$5 = [];
2282
+ }
2283
+ function stop$l() {
2284
+ reset$d();
2285
+ regionMap = null;
2286
+ regions = {};
2287
+ queue$2 = [];
2288
+ if (observer$1) {
2289
+ observer$1.disconnect();
2290
+ observer$1 = null;
2291
+ }
2292
+ watch = false;
2293
+ }
2294
+
2295
+ function offset (element) {
2296
+ var output = { x: 0, y: 0 };
2297
+ // Walk up the chain to ensure we compute offset distance correctly
2298
+ // In case where we may have nested IFRAMEs, we keep walking up until we get to the top most parent page
2299
+ if (element && element.offsetParent) {
2300
+ do {
2301
+ var parent_1 = element.offsetParent;
2302
+ var frame = parent_1 === null ? iframe(element.ownerDocument) : null;
2303
+ output.x += element.offsetLeft;
2304
+ output.y += element.offsetTop;
2305
+ element = frame ? frame : parent_1;
2306
+ } while (element);
2307
+ }
2308
+ return output;
2309
+ }
2310
+
2311
+ var UserInputTags = ["input", "textarea", "radio", "button", "canvas"];
2312
+ var state$4 = [];
2313
+ function start$l() {
2314
+ reset$c();
2315
+ }
2316
+ function observe$8(root) {
2317
+ bind(root, "click", handler$1.bind(this, 9 /* Click */, root), true);
2318
+ }
2319
+ function handler$1(event, root, evt) {
2320
+ var frame = iframe(root);
2321
+ var d = frame ? frame.contentDocument.documentElement : document.documentElement;
2322
+ var x = "pageX" in evt ? Math.round(evt.pageX) : ("clientX" in evt ? Math.round(evt["clientX"] + d.scrollLeft) : null);
2323
+ var y = "pageY" in evt ? Math.round(evt.pageY) : ("clientY" in evt ? Math.round(evt["clientY"] + d.scrollTop) : null);
2324
+ // In case of iframe, we adjust (x,y) to be relative to top parent's origin
2325
+ if (frame) {
2326
+ var distance = offset(frame);
2327
+ x = x ? x + Math.round(distance.x) : x;
2328
+ y = y ? y + Math.round(distance.y) : y;
2329
+ }
2330
+ var t = target(evt);
2331
+ // Find nearest anchor tag (<a/>) parent if current target node is part of one
2332
+ // If present, we use the returned link element to populate text and link properties below
2333
+ var a = link(t);
2334
+ // Get layout rectangle for the target element
2335
+ var l = layout$1(t);
2336
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
2337
+ // This property helps differentiate between a keyboard navigation vs. pointer click
2338
+ // In case of a keyboard navigation, we use center of target element as (x,y)
2339
+ if (evt.detail === 0 && l) {
2340
+ x = Math.round(l.x + (l.w / 2));
2341
+ y = Math.round(l.y + (l.h / 2));
2342
+ }
2343
+ var eX = l ? Math.max(Math.floor(((x - l.x) / l.w) * 32767 /* ClickPrecision */), 0) : 0;
2344
+ var eY = l ? Math.max(Math.floor(((y - l.y) / l.h) * 32767 /* ClickPrecision */), 0) : 0;
2345
+ // Check for null values before processing this event
2346
+ if (x !== null && y !== null) {
2347
+ state$4.push({
2348
+ time: time(),
2349
+ event: event, data: {
2350
+ target: t,
2351
+ x: x,
2352
+ y: y,
2353
+ eX: eX,
2354
+ eY: eY,
2355
+ button: evt.button,
2356
+ reaction: reaction(t),
2357
+ context: context(a),
2358
+ text: text(t),
2359
+ link: a ? a.href : null,
2360
+ hash: null
2361
+ }
2362
+ });
2363
+ schedule$1(encode$2.bind(this, event));
2364
+ }
2365
+ }
2366
+ function text(element) {
2367
+ var output = null;
2368
+ if (element) {
2369
+ // Grab text using "textContent" for most HTMLElements, however, use "value" for HTMLInputElements and "alt" for HTMLImageElement.
2370
+ var t = element.textContent || element.value || element.alt;
2371
+ if (t) {
2372
+ // Trim any spaces at the beginning or at the end of string
2373
+ // Also, replace multiple occurrence of space characters with a single white space
2374
+ // Finally, send only first few characters as specified by the Setting
2375
+ output = t.trim().replace(/\s+/g, " " /* Space */).substr(0, 25 /* ClickText */);
2376
+ }
2377
+ }
2378
+ return output;
2379
+ }
2380
+ function reaction(element) {
2381
+ if (element.nodeType === Node.ELEMENT_NODE) {
2382
+ var tag = element.tagName.toLowerCase();
2383
+ if (UserInputTags.indexOf(tag) >= 0) {
2384
+ return 0 /* False */;
2385
+ }
2386
+ }
2387
+ return 1 /* True */;
2388
+ }
2389
+ function layout$1(element) {
2390
+ var box = null;
2391
+ var de = document.documentElement;
2392
+ if (typeof element.getBoundingClientRect === "function") {
2393
+ // getBoundingClientRect returns rectangle relative positioning to viewport
2394
+ var rect = element.getBoundingClientRect();
2395
+ if (rect && rect.width > 0 && rect.height > 0) {
2396
+ // Add viewport's scroll position to rectangle to get position relative to document origin
2397
+ // Also: using Math.floor() instead of Math.round() because in Edge,
2398
+ // getBoundingClientRect returns partial pixel values (e.g. 162.5px) and Chrome already
2399
+ // floors the value (e.g. 162px). This keeps consistent behavior across browsers.
2400
+ box = {
2401
+ x: Math.floor(rect.left + ("pageXOffset" in window ? window.pageXOffset : de.scrollLeft)),
2402
+ y: Math.floor(rect.top + ("pageYOffset" in window ? window.pageYOffset : de.scrollTop)),
2403
+ w: Math.floor(rect.width),
2404
+ h: Math.floor(rect.height)
2405
+ };
2406
+ }
2407
+ }
2408
+ return box;
2409
+ }
2410
+ function context(a) {
2411
+ if (a && a.hasAttribute("target" /* Target */)) {
2412
+ switch (a.getAttribute("target" /* Target */)) {
2413
+ case "_blank" /* Blank */: return 1 /* Blank */;
2414
+ case "_parent" /* Parent */: return 2 /* Parent */;
2415
+ case "_top" /* Top */: return 3 /* Top */;
2416
+ }
2417
+ }
2418
+ return 0 /* Self */;
2419
+ }
2420
+ function reset$c() {
2421
+ state$4 = [];
2422
+ }
2423
+ function stop$k() {
2424
+ reset$c();
2425
+ }
2426
+
2427
+ var timeout$5 = null;
2428
+ var state$3 = [];
2429
+ function start$k() {
2430
+ reset$b();
2431
+ }
2432
+ function observe$7(root) {
2433
+ bind(root, "input", recompute$6, true);
2434
+ }
2435
+ function recompute$6(evt) {
2436
+ var input = target(evt);
2437
+ var value = get(input);
2438
+ if (input && input.type && value) {
2439
+ var v = void 0;
2440
+ switch (input.type) {
2441
+ case "radio":
2442
+ case "checkbox":
2443
+ v = input.checked ? "true" : "false";
2444
+ break;
2445
+ case "range":
2446
+ v = input.value;
2447
+ break;
2448
+ default:
2449
+ v = scrub(input.value, "input", value.metadata.privacy);
2450
+ break;
2451
+ }
2452
+ var data = { target: input, value: v };
2453
+ // If last entry in the queue is for the same target node as the current one, remove it so we can later swap it with current data.
2454
+ if (state$3.length > 0 && (state$3[state$3.length - 1].data.target === data.target)) {
2455
+ state$3.pop();
2456
+ }
2457
+ state$3.push({ time: time(), event: 27 /* Input */, data: data });
2458
+ clearTimeout(timeout$5);
2459
+ timeout$5 = setTimeout(process$5, 500 /* LookAhead */, 27 /* Input */);
2460
+ }
2461
+ }
2462
+ function process$5(event) {
2463
+ schedule$1(encode$2.bind(this, event));
2464
+ }
2465
+ function reset$b() {
2466
+ state$3 = [];
2467
+ }
2468
+ function stop$j() {
2469
+ clearTimeout(timeout$5);
2470
+ reset$b();
2471
+ }
2472
+
2473
+ var state$2 = [];
2474
+ var timeout$4 = null;
2475
+ function start$j() {
2476
+ reset$a();
2477
+ }
2478
+ function observe$6(root) {
2479
+ bind(root, "mousedown", mouse.bind(this, 13 /* MouseDown */, root), true);
2480
+ bind(root, "mouseup", mouse.bind(this, 14 /* MouseUp */, root), true);
2481
+ bind(root, "mousemove", mouse.bind(this, 12 /* MouseMove */, root), true);
2482
+ bind(root, "mousewheel", mouse.bind(this, 15 /* MouseWheel */, root), true);
2483
+ bind(root, "dblclick", mouse.bind(this, 16 /* DoubleClick */, root), true);
2484
+ bind(root, "touchstart", touch.bind(this, 17 /* TouchStart */, root), true);
2485
+ bind(root, "touchend", touch.bind(this, 18 /* TouchEnd */, root), true);
2486
+ bind(root, "touchmove", touch.bind(this, 19 /* TouchMove */, root), true);
2487
+ bind(root, "touchcancel", touch.bind(this, 20 /* TouchCancel */, root), true);
2488
+ }
2489
+ function mouse(event, root, evt) {
2490
+ var frame = iframe(root);
2491
+ var d = frame ? frame.contentDocument.documentElement : document.documentElement;
2492
+ var x = "pageX" in evt ? Math.round(evt.pageX) : ("clientX" in evt ? Math.round(evt["clientX"] + d.scrollLeft) : null);
2493
+ var y = "pageY" in evt ? Math.round(evt.pageY) : ("clientY" in evt ? Math.round(evt["clientY"] + d.scrollTop) : null);
2494
+ // In case of iframe, we adjust (x,y) to be relative to top parent's origin
2495
+ if (frame) {
2496
+ var distance = offset(frame);
2497
+ x = x ? x + Math.round(distance.x) : x;
2498
+ y = y ? y + Math.round(distance.y) : y;
2499
+ }
2500
+ // Check for null values before processing this event
2501
+ if (x !== null && y !== null) {
2502
+ handler({ time: time(), event: event, data: { target: target(evt), x: x, y: y } });
2503
+ }
2504
+ }
2505
+ function touch(event, root, evt) {
2506
+ var frame = iframe(root);
2507
+ var d = frame ? frame.contentDocument.documentElement : document.documentElement;
2508
+ var touches = evt.changedTouches;
2509
+ var t = time();
2510
+ if (touches) {
2511
+ for (var i = 0; i < touches.length; i++) {
2512
+ var entry = touches[i];
2513
+ var x = "clientX" in entry ? Math.round(entry["clientX"] + d.scrollLeft) : null;
2514
+ var y = "clientY" in entry ? Math.round(entry["clientY"] + d.scrollTop) : null;
2515
+ x = x && frame ? x + Math.round(frame.offsetLeft) : x;
2516
+ y = y && frame ? y + Math.round(frame.offsetTop) : y;
2517
+ // Check for null values before processing this event
2518
+ if (x !== null && y !== null) {
2519
+ handler({ time: t, event: event, data: { target: target(evt), x: x, y: y } });
2520
+ }
2521
+ }
2522
+ }
2523
+ }
2524
+ function handler(current) {
2525
+ switch (current.event) {
2526
+ case 12 /* MouseMove */:
2527
+ case 15 /* MouseWheel */:
2528
+ case 19 /* TouchMove */:
2529
+ var length_1 = state$2.length;
2530
+ var last = length_1 > 1 ? state$2[length_1 - 2] : null;
2531
+ if (last && similar$1(last, current)) {
2532
+ state$2.pop();
2533
+ }
2534
+ state$2.push(current);
2535
+ clearTimeout(timeout$4);
2536
+ timeout$4 = setTimeout(process$4, 500 /* LookAhead */, current.event);
2537
+ break;
2538
+ default:
2539
+ state$2.push(current);
2540
+ process$4(current.event);
2541
+ break;
2542
+ }
2543
+ }
2544
+ function process$4(event) {
2545
+ schedule$1(encode$2.bind(this, event));
2546
+ }
2547
+ function reset$a() {
2548
+ state$2 = [];
2549
+ }
2550
+ function similar$1(last, current) {
2551
+ var dx = last.data.x - current.data.x;
2552
+ var dy = last.data.y - current.data.y;
2553
+ var distance = Math.sqrt(dx * dx + dy * dy);
2554
+ var gap = current.time - last.time;
2555
+ var match = current.data.target === last.data.target;
2556
+ return current.event === last.event && match && distance < 20 /* Distance */ && gap < 25 /* Interval */;
2557
+ }
2558
+ function stop$i() {
2559
+ clearTimeout(timeout$4);
2560
+ // Send out any pending pointer events in the pipeline
2561
+ if (state$2.length > 0) {
2562
+ process$4(state$2[state$2.length - 1].event);
2563
+ }
2564
+ }
2565
+
2566
+ var data$6;
2567
+ function start$i() {
2568
+ bind(window, "resize", recompute$5);
2569
+ recompute$5();
2570
+ }
2571
+ function recompute$5() {
2572
+ var de = document.documentElement;
2573
+ // window.innerWidth includes width of the scrollbar and is not a true representation of the viewport width.
2574
+ // Therefore, when possible, use documentElement's clientWidth property.
2575
+ data$6 = {
2576
+ width: de && "clientWidth" in de ? Math.min(de.clientWidth, window.innerWidth) : window.innerWidth,
2577
+ height: de && "clientHeight" in de ? Math.min(de.clientHeight, window.innerHeight) : window.innerHeight,
2578
+ };
2579
+ encode$2(11 /* Resize */);
2580
+ }
2581
+ function reset$9() {
2582
+ data$6 = null;
2583
+ }
2584
+ function stop$h() {
2585
+ reset$9();
2586
+ }
2587
+
2588
+ var state$1 = [];
2589
+ var timeout$3 = null;
2590
+ function start$h() {
2591
+ state$1 = [];
2592
+ recompute$4();
2593
+ }
2594
+ function observe$5(root) {
2595
+ var frame = iframe(root);
2596
+ var node = frame ? frame.contentWindow : (root === document ? window : root);
2597
+ bind(node, "scroll", recompute$4, true);
2598
+ }
2599
+ function recompute$4(event) {
2600
+ if (event === void 0) { event = null; }
2601
+ var w = window;
2602
+ var de = document.documentElement;
2603
+ var element = event ? target(event) : de;
2604
+ // If the target is a Document node, then identify corresponding documentElement and window for this document
2605
+ if (element && element.nodeType === Node.DOCUMENT_NODE) {
2606
+ var frame = iframe(element);
2607
+ w = frame ? frame.contentWindow : w;
2608
+ element = de = element.documentElement;
2609
+ }
2610
+ // Edge doesn't support scrollTop position on document.documentElement.
2611
+ // For cross browser compatibility, looking up pageYOffset on window if the scroll is on document.
2612
+ // And, if for some reason that is not available, fall back to looking up scrollTop on document.documentElement.
2613
+ var x = element === de && "pageXOffset" in w ? Math.round(w.pageXOffset) : Math.round(element.scrollLeft);
2614
+ var y = element === de && "pageYOffset" in w ? Math.round(w.pageYOffset) : Math.round(element.scrollTop);
2615
+ var current = { time: time(), event: 10 /* Scroll */, data: { target: element, x: x, y: y } };
2616
+ // We don't send any scroll events if this is the first event and the current position is top (0,0)
2617
+ if ((event === null && x === 0 && y === 0) || (x === null || y === null)) {
2618
+ return;
2619
+ }
2620
+ var length = state$1.length;
2621
+ var last = length > 1 ? state$1[length - 2] : null;
2622
+ if (last && similar(last, current)) {
2623
+ state$1.pop();
2624
+ }
2625
+ state$1.push(current);
2626
+ clearTimeout(timeout$3);
2627
+ timeout$3 = setTimeout(process$3, 500 /* LookAhead */, 10 /* Scroll */);
2628
+ }
2629
+ function reset$8() {
2630
+ state$1 = [];
2631
+ }
2632
+ function process$3(event) {
2633
+ schedule$1(encode$2.bind(this, event));
2634
+ }
2635
+ function similar(last, current) {
2636
+ var dx = last.data.x - current.data.x;
2637
+ var dy = last.data.y - current.data.y;
2638
+ return (dx * dx + dy * dy < 20 /* Distance */ * 20 /* Distance */) && (current.time - last.time < 25 /* Interval */);
2639
+ }
2640
+ function stop$g() {
2641
+ clearTimeout(timeout$3);
2642
+ state$1 = [];
2643
+ }
2644
+
2645
+ var data$5 = null;
2646
+ var previous = null;
2647
+ var timeout$2 = null;
2648
+ function start$g() {
2649
+ reset$7();
2650
+ }
2651
+ function observe$4(root) {
2652
+ bind(root, "selectstart", recompute$3.bind(this, root), true);
2653
+ bind(root, "selectionchange", recompute$3.bind(this, root), true);
2654
+ }
2655
+ function recompute$3(root) {
2656
+ var doc = root.nodeType === Node.DOCUMENT_NODE ? root : document;
2657
+ var current = doc.getSelection();
2658
+ // Bail out if we don't have a valid selection
2659
+ if (current === null) {
2660
+ return;
2661
+ }
2662
+ // Bail out if we got a valid selection but not valid nodes
2663
+ // In Edge, selectionchange gets fired even on interactions like right clicks and
2664
+ // can result in null anchorNode and focusNode if there was no previous selection on page
2665
+ // Also, ignore any selections that start and end at the exact same point
2666
+ if ((current.anchorNode === null && current.focusNode === null) ||
2667
+ (current.anchorNode === current.focusNode && current.anchorOffset === current.focusOffset)) {
2668
+ return;
2669
+ }
2670
+ var startNode = data$5.start ? data$5.start : null;
2671
+ if (previous !== null && data$5.start !== null && startNode !== current.anchorNode) {
2672
+ clearTimeout(timeout$2);
2673
+ process$2(21 /* Selection */);
2674
+ }
2675
+ data$5 = {
2676
+ start: current.anchorNode,
2677
+ startOffset: current.anchorOffset,
2678
+ end: current.focusNode,
2679
+ endOffset: current.focusOffset
2680
+ };
2681
+ previous = current;
2682
+ clearTimeout(timeout$2);
2683
+ timeout$2 = setTimeout(process$2, 500 /* LookAhead */, 21 /* Selection */);
2684
+ }
2685
+ function process$2(event) {
2686
+ schedule$1(encode$2.bind(this, event));
2687
+ }
2688
+ function reset$7() {
2689
+ previous = null;
2690
+ data$5 = { start: 0, startOffset: 0, end: 0, endOffset: 0 };
2691
+ }
2692
+ function stop$f() {
2693
+ reset$7();
2694
+ clearTimeout(timeout$2);
2695
+ }
2696
+
2697
+ var data$4;
2698
+ function start$f() {
2699
+ bind(window, "pagehide", recompute$2);
2700
+ }
2701
+ function recompute$2(evt) {
2702
+ data$4 = { name: evt.type };
2703
+ encode$2(26 /* Unload */);
2704
+ stop();
2705
+ }
2706
+ function reset$6() {
2707
+ data$4 = null;
2708
+ }
2709
+ function stop$e() {
2710
+ reset$6();
2711
+ }
2712
+
2713
+ var data$3;
2714
+ function start$e() {
2715
+ bind(document, "visibilitychange", recompute$1);
2716
+ recompute$1();
2717
+ }
2718
+ function recompute$1() {
2719
+ data$3 = { visible: "visibilityState" in document ? document.visibilityState : "default" };
2720
+ encode$2(28 /* Visibility */);
2721
+ }
2722
+ function reset$5() {
2723
+ data$3 = null;
2724
+ }
2725
+ function stop$d() {
2726
+ reset$5();
2727
+ }
2728
+
2729
+ function start$d() {
2730
+ start$b();
2731
+ start$l();
2732
+ start$j();
2733
+ start$k();
2734
+ start$i();
2735
+ start$e();
2736
+ start$h();
2737
+ start$g();
2738
+ start$f();
2739
+ }
2740
+ function stop$c() {
2741
+ stop$a();
2742
+ stop$k();
2743
+ stop$i();
2744
+ stop$j();
2745
+ stop$h();
2746
+ stop$d();
2747
+ stop$g();
2748
+ stop$f();
2749
+ stop$e();
2750
+ }
2751
+ function observe$3(root) {
2752
+ observe$5(root);
2753
+ // Only monitor following interactions if the root node is a document
2754
+ // In case of shadow DOM, following events automatically bubble up to the parent document.
2755
+ if (root.nodeType === Node.DOCUMENT_NODE) {
2756
+ observe$8(root);
2757
+ observe$6(root);
2758
+ observe$7(root);
2759
+ observe$4(root);
2760
+ }
2761
+ }
2762
+
2763
+ var interaction = /*#__PURE__*/Object.freeze({
2764
+ __proto__: null,
2765
+ start: start$d,
2766
+ stop: stop$c,
2767
+ observe: observe$3
2768
+ });
2769
+
2770
+ var digitsRegex = /[^0-9\.]/g;
2771
+ /* JSON+LD (Linked Data) Recursive Parser */
2772
+ function ld(json) {
2773
+ for (var _i = 0, _a = Object.keys(json); _i < _a.length; _i++) {
2774
+ var key = _a[_i];
2775
+ var value = json[key];
2776
+ if (key === "@type" /* Type */ && typeof value === "string") {
2777
+ value = value.toLowerCase();
2778
+ /* Normalizations */
2779
+ value = value.indexOf("article" /* Article */) >= 0 || value.indexOf("posting" /* Posting */) >= 0 ? "article" /* Article */ : value;
2780
+ switch (value) {
2781
+ case "article" /* Article */:
2782
+ case "recipe" /* Recipe */:
2783
+ log$1(5 /* SchemaType */, json[key]);
2784
+ log$1(8 /* AuthorName */, json["creator" /* Creator */]);
2785
+ log$1(18 /* Headline */, json["headline" /* Headline */]);
2786
+ break;
2787
+ case "product" /* Product */:
2788
+ log$1(5 /* SchemaType */, json[key]);
2789
+ log$1(10 /* ProductName */, json["name" /* Name */]);
2790
+ log$1(12 /* ProductSku */, json["sku" /* Sku */]);
2791
+ if (json["brand" /* Brand */]) {
2792
+ log$1(6 /* ProductBrand */, json["brand" /* Brand */]["name" /* Name */]);
2793
+ }
2794
+ break;
2795
+ case "aggregaterating" /* AggregateRating */:
2796
+ if (json["ratingValue" /* RatingValue */]) {
2797
+ max(11 /* RatingValue */, num(json["ratingValue" /* RatingValue */], 100 /* RatingScale */));
2798
+ max(18 /* BestRating */, num(json["bestRating" /* BestRating */]));
2799
+ max(19 /* WorstRating */, num(json["worstRating" /* WorstRating */]));
2800
+ }
2801
+ max(12 /* RatingCount */, num(json["ratingCount" /* RatingCount */]));
2802
+ max(17 /* ReviewCount */, num(json["reviewCount" /* ReviewCount */]));
2803
+ break;
2804
+ case "person" /* Author */:
2805
+ log$1(8 /* AuthorName */, json["name" /* Name */]);
2806
+ break;
2807
+ case "offer" /* Offer */:
2808
+ log$1(7 /* ProductAvailability */, json["availability" /* Availability */]);
2809
+ log$1(14 /* ProductCondition */, json["itemCondition" /* ItemCondition */]);
2810
+ log$1(13 /* ProductCurrency */, json["priceCurrency" /* PriceCurrency */]);
2811
+ log$1(12 /* ProductSku */, json["sku" /* Sku */]);
2812
+ max(13 /* ProductPrice */, num(json["price" /* Price */]));
2813
+ break;
2814
+ case "brand" /* Brand */:
2815
+ log$1(6 /* ProductBrand */, json["name" /* Name */]);
2816
+ break;
2817
+ }
2818
+ }
2819
+ // Continue parsing nested objects
2820
+ if (value !== null && typeof (value) === "object" /* Object */) {
2821
+ ld(value);
2822
+ }
2823
+ }
2824
+ }
2825
+ function num(input, scale) {
2826
+ if (scale === void 0) { scale = 1; }
2827
+ if (input !== null) {
2828
+ switch (typeof input) {
2829
+ case "number" /* Number */: return Math.round(input * scale);
2830
+ case "string" /* String */: return Math.round(parseFloat(input.replace(digitsRegex, "" /* Empty */)) * scale);
2831
+ }
2832
+ }
2833
+ return null;
2834
+ }
2835
+
2836
+ var IGNORE_ATTRIBUTES = ["title", "alt", "onload", "onfocus", "onerror"];
2837
+ function processNode (node, source) {
2838
+ var child = null;
2839
+ // Do not track this change if we are attempting to remove a node before discovering it
2840
+ if (source === 2 /* ChildListRemove */ && has(node) === false) {
2841
+ return child;
2842
+ }
2843
+ // Special handling for text nodes that belong to style nodes
2844
+ if (source !== 0 /* Discover */ &&
2845
+ node.nodeType === Node.TEXT_NODE &&
2846
+ node.parentElement &&
2847
+ node.parentElement.tagName === "STYLE") {
2848
+ node = node.parentNode;
2849
+ }
2850
+ var add = has(node) === false;
2851
+ var call = add ? "add" : "update";
2852
+ var parent = node.parentElement ? node.parentElement : null;
2853
+ var insideFrame = node.ownerDocument !== document;
2854
+ switch (node.nodeType) {
2855
+ case Node.DOCUMENT_TYPE_NODE:
2856
+ parent = insideFrame && node.parentNode ? iframe(node.parentNode) : parent;
2857
+ var docTypePrefix = insideFrame ? "iframe:" /* IFramePrefix */ : "" /* Empty */;
2858
+ var doctype = node;
2859
+ var docAttributes = { name: doctype.name, publicId: doctype.publicId, systemId: doctype.systemId };
2860
+ var docData = { tag: docTypePrefix + "*D" /* DocumentTag */, attributes: docAttributes };
2861
+ dom[call](node, parent, docData, source);
2862
+ break;
2863
+ case Node.DOCUMENT_NODE:
2864
+ // We check for regions in the beginning when discovering document and
2865
+ // later whenever there are new additions or modifications to DOM (mutations)
2866
+ if (node === document)
2867
+ parse(document);
2868
+ observe$2(node);
2869
+ break;
2870
+ case Node.DOCUMENT_FRAGMENT_NODE:
2871
+ var shadowRoot = node;
2872
+ if (shadowRoot.host) {
2873
+ var type = typeof (shadowRoot.constructor);
2874
+ if (type === "function" /* Function */ && shadowRoot.constructor.toString().indexOf("[native code]" /* NativeCode */) >= 0) {
2875
+ observe$2(shadowRoot);
2876
+ // See: https://wicg.github.io/construct-stylesheets/ for more details on adoptedStyleSheets.
2877
+ // At the moment, we are only able to capture "open" shadow DOM nodes. If they are closed, they are not accessible.
2878
+ // In future we may decide to proxy "attachShadow" call to gain access, but at the moment, we don't want to
2879
+ // cause any unintended side effect to the page. We will re-evaluate after we gather more real world data on this.
2880
+ var style = "" /* Empty */;
2881
+ var adoptedStyleSheets = "adoptedStyleSheets" in shadowRoot ? shadowRoot["adoptedStyleSheets"] : [];
2882
+ for (var _i = 0, adoptedStyleSheets_1 = adoptedStyleSheets; _i < adoptedStyleSheets_1.length; _i++) {
2883
+ var styleSheet = adoptedStyleSheets_1[_i];
2884
+ style += getCssRules(styleSheet);
2885
+ }
2886
+ var fragementData = { tag: "*S" /* ShadowDomTag */, attributes: { style: style } };
2887
+ dom[call](node, shadowRoot.host, fragementData, source);
2888
+ }
2889
+ else {
2890
+ // If the browser doesn't support shadow DOM natively, we detect that, and send appropriate tag back.
2891
+ // The differentiation is important because we don't have to observe pollyfill shadow DOM nodes,
2892
+ // the same way we observe real shadow DOM nodes (encapsulation provided by the browser).
2893
+ dom[call](node, shadowRoot.host, { tag: "*P" /* PolyfillShadowDomTag */, attributes: {} }, source);
2894
+ }
2895
+ }
2896
+ break;
2897
+ case Node.TEXT_NODE:
2898
+ // In IE11 TEXT_NODE doesn't expose a valid parentElement property. Instead we need to lookup parentNode property.
2899
+ parent = parent ? parent : node.parentNode;
2900
+ // Account for this text node only if we are tracking the parent node
2901
+ // We do not wish to track text nodes for ignored parent nodes, like script tags
2902
+ // Also, we do not track text nodes for STYLE tags
2903
+ // The only exception is when we receive a mutation to remove the text node, in that case
2904
+ // parent will be null, but we can still process the node by checking it's an update call.
2905
+ if (call === "update" || (parent && has(parent) && parent.tagName !== "STYLE")) {
2906
+ var textData = { tag: "*T" /* TextTag */, value: node.nodeValue };
2907
+ dom[call](node, parent, textData, source);
2908
+ }
2909
+ break;
2910
+ case Node.ELEMENT_NODE:
2911
+ var element = node;
2912
+ var tag = element.tagName;
2913
+ var attributes = getAttributes(element);
2914
+ // In some cases, external libraries like vue-fragment, can modify parentNode property to not be in sync with the DOM
2915
+ // For correctness, we first look at parentElement and if it not present then fall back to using parentNode
2916
+ parent = node.parentElement ? node.parentElement : (node.parentNode ? node.parentNode : null);
2917
+ // If we encounter a node that is part of SVG namespace, prefix the tag with SVG_PREFIX
2918
+ if (element.namespaceURI === "http://www.w3.org/2000/svg" /* SvgNamespace */) {
2919
+ tag = "svg:" /* SvgPrefix */ + tag;
2920
+ }
2921
+ switch (tag) {
2922
+ case "HTML":
2923
+ parent = insideFrame && parent ? iframe(parent) : null;
2924
+ var htmlPrefix = insideFrame ? "iframe:" /* IFramePrefix */ : "" /* Empty */;
2925
+ var htmlData = { tag: htmlPrefix + tag, attributes: attributes };
2926
+ dom[call](node, parent, htmlData, source);
2927
+ break;
2928
+ case "SCRIPT":
2929
+ if ("type" /* Type */ in attributes && attributes["type" /* Type */] === "application/ld+json" /* JsonLD */) {
2930
+ try {
2931
+ ld(JSON.parse(element.text));
2932
+ }
2933
+ catch ( /* do nothing */_a) { /* do nothing */ }
2934
+ }
2935
+ break;
2936
+ case "NOSCRIPT":
2937
+ break;
2938
+ case "META":
2939
+ if ("property" /* Property */ in attributes && "content" /* Content */ in attributes) {
2940
+ var content = attributes["content" /* Content */];
2941
+ switch (attributes["property" /* Property */]) {
2942
+ case "og:title" /* ogTitle */:
2943
+ log$1(20 /* MetaTitle */, content);
2944
+ break;
2945
+ case "og:type" /* ogType */:
2946
+ log$1(19 /* MetaType */, content);
2947
+ break;
2948
+ case "generator" /* Generator */:
2949
+ log$1(21 /* Generator */, content);
2950
+ break;
2951
+ }
2952
+ }
2953
+ break;
2954
+ case "HEAD":
2955
+ var head = { tag: tag, attributes: attributes };
2956
+ if (location) {
2957
+ head.attributes["*B" /* Base */] = location.protocol + "//" + location.hostname;
2958
+ }
2959
+ dom[call](node, parent, head, source);
2960
+ break;
2961
+ case "STYLE":
2962
+ var styleData = { tag: tag, attributes: attributes, value: getStyleValue(element) };
2963
+ dom[call](node, parent, styleData, source);
2964
+ break;
2965
+ case "IFRAME":
2966
+ var iframe$1 = node;
2967
+ var frameData = { tag: tag, attributes: attributes };
2968
+ if (sameorigin(iframe$1)) {
2969
+ monitor(iframe$1);
2970
+ frameData.attributes["*O" /* SameOrigin */] = "true";
2971
+ if (iframe$1.contentDocument && iframe$1.contentWindow && iframe$1.contentDocument.readyState !== "loading") {
2972
+ child = iframe$1.contentDocument;
2973
+ }
2974
+ }
2975
+ dom[call](node, parent, frameData, source);
2976
+ break;
2977
+ default:
2978
+ var data = { tag: tag, attributes: attributes };
2979
+ if (element.shadowRoot) {
2980
+ child = element.shadowRoot;
2981
+ }
2982
+ dom[call](node, parent, data, source);
2983
+ break;
2984
+ }
2985
+ break;
2986
+ }
2987
+ return child;
2988
+ }
2989
+ function observe$2(root) {
2990
+ if (has(root)) {
2991
+ return;
2992
+ }
2993
+ observe$1(root); // Observe mutations for this root node
2994
+ observe$3(root); // Observe interactions for this root node
2995
+ }
2996
+ function getStyleValue(style) {
2997
+ // Call trim on the text content to ensure we do not process white spaces ( , \n, \r\n, \t, etc.)
2998
+ // Also, check if stylesheet has any data-* attribute, if so process rules instead of looking up text
2999
+ var value = style.textContent ? style.textContent.trim() : "" /* Empty */;
3000
+ var dataset = style.dataset ? Object.keys(style.dataset).length : 0;
3001
+ if (value.length === 0 || dataset > 0 || config$1.cssRules) {
3002
+ value = getCssRules(style.sheet);
3003
+ }
3004
+ return value;
3005
+ }
3006
+ function getCssRules(sheet) {
3007
+ var value = "" /* Empty */;
3008
+ var cssRules = null;
3009
+ // Firefox throws a SecurityError when trying to access cssRules of a stylesheet from a different domain
3010
+ try {
3011
+ cssRules = sheet ? sheet.cssRules : [];
3012
+ }
3013
+ catch (e) {
3014
+ log(1 /* CssRules */, 1 /* Warning */, e ? e.name : null);
3015
+ if (e && e.name !== "SecurityError") {
3016
+ throw e;
3017
+ }
3018
+ }
3019
+ if (cssRules !== null) {
3020
+ for (var i = 0; i < cssRules.length; i++) {
3021
+ value += cssRules[i].cssText;
3022
+ }
3023
+ }
3024
+ return value;
3025
+ }
3026
+ function getAttributes(element) {
3027
+ var output = {};
3028
+ var attributes = element.attributes;
3029
+ if (attributes && attributes.length > 0) {
3030
+ for (var i = 0; i < attributes.length; i++) {
3031
+ var name_1 = attributes[i].name;
3032
+ if (IGNORE_ATTRIBUTES.indexOf(name_1) < 0) {
3033
+ output[name_1] = attributes[i].value;
3034
+ }
3035
+ }
3036
+ }
3037
+ // For INPUT tags read the dynamic "value" property if an explicit "value" attribute is not set
3038
+ if (element.tagName === "INPUT" /* InputTag */ && !("value" /* Value */ in output) && element.value) {
3039
+ output["value" /* Value */] = element.value;
3040
+ }
3041
+ return output;
3042
+ }
3043
+
3044
+ function traverse (root, timer, source) {
3045
+ return __awaiter(this, void 0, void 0, function () {
3046
+ var queue, node, next, state, subnode;
3047
+ return __generator(this, function (_a) {
3048
+ switch (_a.label) {
3049
+ case 0:
3050
+ queue = [root];
3051
+ _a.label = 1;
3052
+ case 1:
3053
+ if (!(queue.length > 0)) return [3 /*break*/, 4];
3054
+ node = queue.shift();
3055
+ next = node.firstChild;
3056
+ while (next) {
3057
+ queue.push(next);
3058
+ next = next.nextSibling;
3059
+ }
3060
+ state = state$6(timer);
3061
+ if (!(state === 0 /* Wait */)) return [3 /*break*/, 3];
3062
+ return [4 /*yield*/, suspend$1(timer)];
3063
+ case 2:
3064
+ state = _a.sent();
3065
+ _a.label = 3;
3066
+ case 3:
3067
+ if (state === 2 /* Stop */) {
3068
+ return [3 /*break*/, 4];
3069
+ }
3070
+ subnode = processNode(node, source);
3071
+ if (subnode) {
3072
+ queue.push(subnode);
3073
+ }
3074
+ return [3 /*break*/, 1];
3075
+ case 4: return [2 /*return*/];
3076
+ }
3077
+ });
3078
+ });
3079
+ }
3080
+
3081
+ var observers = [];
3082
+ var mutations = [];
3083
+ var insertRule = null;
3084
+ var deleteRule = null;
3085
+ var queue$1 = [];
3086
+ var timeout$1 = null;
3087
+ var activePeriod = null;
3088
+ var history$1 = {};
3089
+ function start$c() {
3090
+ observers = [];
3091
+ queue$1 = [];
3092
+ timeout$1 = null;
3093
+ activePeriod = 0;
3094
+ history$1 = {};
3095
+ if (insertRule === null) {
3096
+ insertRule = CSSStyleSheet.prototype.insertRule;
3097
+ }
3098
+ if (deleteRule === null) {
3099
+ deleteRule = CSSStyleSheet.prototype.deleteRule;
3100
+ }
3101
+ // Some popular open source libraries, like styled-components, optimize performance
3102
+ // by injecting CSS using insertRule API vs. appending text node. A side effect of
3103
+ // using javascript API is that it doesn't trigger DOM mutation and therefore we
3104
+ // need to override the insertRule API and listen for changes manually.
3105
+ CSSStyleSheet.prototype.insertRule = function () {
3106
+ schedule(this.ownerNode);
3107
+ return insertRule.apply(this, arguments);
3108
+ };
3109
+ CSSStyleSheet.prototype.deleteRule = function () {
3110
+ schedule(this.ownerNode);
3111
+ return deleteRule.apply(this, arguments);
3112
+ };
3113
+ }
3114
+ function observe$1(node) {
3115
+ // Create a new observer for every time a new DOM tree (e.g. root document or shadowdom root) is discovered on the page
3116
+ // In the case of shadow dom, any mutations that happen within the shadow dom are not bubbled up to the host document
3117
+ // For this reason, we need to wire up mutations every time we see a new shadow dom.
3118
+ // Also, wrap it inside a try / catch. In certain browsers (e.g. legacy Edge), observer on shadow dom can throw errors
3119
+ try {
3120
+ // In an edge case, it's possible to get stuck into infinite Mutation loop within Angular applications
3121
+ // This appears to be an issue with Zone.js package, see: https://github.com/angular/angular/issues/31712
3122
+ // As a temporary work around, ensuring Clarity can invoke MutationObserver outside of Zone (and use native implementation instead)
3123
+ var api = window["Zone" /* Zone */] && "__symbol__" /* Symbol */ in window["Zone" /* Zone */] ? window["Zone" /* Zone */]["__symbol__" /* Symbol */]("MutationObserver" /* MutationObserver */) : "MutationObserver" /* MutationObserver */;
3124
+ var observer = api in window ? new window[api](measure(handle$1)) : null;
3125
+ if (observer) {
3126
+ observer.observe(node, { attributes: true, childList: true, characterData: true, subtree: true });
3127
+ observers.push(observer);
3128
+ }
3129
+ }
3130
+ catch (e) {
3131
+ log(2 /* MutationObserver */, 0 /* Info */, e ? e.name : null);
3132
+ }
3133
+ }
3134
+ function monitor(frame) {
3135
+ // Bind to iframe's onload event so we get notified anytime there's an update to iframe content.
3136
+ // This includes cases where iframe location is updated without explicitly updating src attribute
3137
+ // E.g. iframe.contentWindow.location.href = "new-location";
3138
+ if (has(frame) === false) {
3139
+ bind(frame, "load" /* LoadEvent */, generate.bind(this, frame, "childList" /* ChildList */), true);
3140
+ }
3141
+ }
3142
+ function stop$b() {
3143
+ for (var _i = 0, observers_1 = observers; _i < observers_1.length; _i++) {
3144
+ var observer = observers_1[_i];
3145
+ if (observer) {
3146
+ observer.disconnect();
3147
+ }
3148
+ }
3149
+ observers = [];
3150
+ // Restoring original insertRule
3151
+ if (insertRule !== null) {
3152
+ CSSStyleSheet.prototype.insertRule = insertRule;
3153
+ insertRule = null;
3154
+ }
3155
+ // Restoring original deleteRule
3156
+ if (deleteRule !== null) {
3157
+ CSSStyleSheet.prototype.deleteRule = deleteRule;
3158
+ deleteRule = null;
3159
+ }
3160
+ history$1 = {};
3161
+ mutations = [];
3162
+ queue$1 = [];
3163
+ activePeriod = 0;
3164
+ timeout$1 = null;
3165
+ }
3166
+ function active$2() {
3167
+ activePeriod = time() + 3000 /* MutationActivePeriod */;
3168
+ }
3169
+ function handle$1(m) {
3170
+ // Queue up mutation records for asynchronous processing
3171
+ var now = time();
3172
+ track$5(6 /* Mutation */, now);
3173
+ mutations.push({ time: now, mutations: m });
3174
+ schedule$1(process$1, 1 /* High */).then(function () {
3175
+ measure(compute$6)();
3176
+ measure(compute$4)();
3177
+ });
3178
+ }
3179
+ function process$1() {
3180
+ return __awaiter(this, void 0, void 0, function () {
3181
+ var timer, record, _i, _a, mutation, state, target, type, value;
3182
+ return __generator(this, function (_b) {
3183
+ switch (_b.label) {
3184
+ case 0:
3185
+ timer = { id: id(), cost: 3 /* LayoutCost */ };
3186
+ start$t(timer);
3187
+ _b.label = 1;
3188
+ case 1:
3189
+ if (!(mutations.length > 0)) return [3 /*break*/, 8];
3190
+ record = mutations.shift();
3191
+ _i = 0, _a = record.mutations;
3192
+ _b.label = 2;
3193
+ case 2:
3194
+ if (!(_i < _a.length)) return [3 /*break*/, 6];
3195
+ mutation = _a[_i];
3196
+ state = state$6(timer);
3197
+ if (!(state === 0 /* Wait */)) return [3 /*break*/, 4];
3198
+ return [4 /*yield*/, suspend$1(timer)];
3199
+ case 3:
3200
+ state = _b.sent();
3201
+ _b.label = 4;
3202
+ case 4:
3203
+ if (state === 2 /* Stop */) {
3204
+ return [3 /*break*/, 6];
3205
+ }
3206
+ target = mutation.target;
3207
+ type = track$2(mutation, timer);
3208
+ if (type && target && target.ownerDocument) {
3209
+ parse(target.ownerDocument);
3210
+ }
3211
+ switch (type) {
3212
+ case "attributes" /* Attributes */:
3213
+ processNode(target, 3 /* Attributes */);
3214
+ break;
3215
+ case "characterData" /* CharacterData */:
3216
+ processNode(target, 4 /* CharacterData */);
3217
+ break;
3218
+ case "childList" /* ChildList */:
3219
+ processNodeList(mutation.addedNodes, 1 /* ChildListAdd */, timer);
3220
+ processNodeList(mutation.removedNodes, 2 /* ChildListRemove */, timer);
3221
+ break;
3222
+ case "suspend" /* Suspend */:
3223
+ value = get(target);
3224
+ if (value) {
3225
+ value.data.tag = "*M" /* SuspendMutationTag */;
3226
+ }
3227
+ break;
3228
+ }
3229
+ _b.label = 5;
3230
+ case 5:
3231
+ _i++;
3232
+ return [3 /*break*/, 2];
3233
+ case 6: return [4 /*yield*/, encode$4(6 /* Mutation */, timer, record.time)];
3234
+ case 7:
3235
+ _b.sent();
3236
+ return [3 /*break*/, 1];
3237
+ case 8:
3238
+ stop$q(timer);
3239
+ return [2 /*return*/];
3240
+ }
3241
+ });
3242
+ });
3243
+ }
3244
+ function track$2(m, timer) {
3245
+ var value = m.target ? get(m.target.parentNode) : null;
3246
+ // Check if the parent is already discovered and that the parent is not the document root
3247
+ if (value && value.selector !== "HTML" /* HTML */) {
3248
+ var inactive = time() > activePeriod;
3249
+ var target = get(m.target);
3250
+ var element = target ? target.selector : m.target.nodeName;
3251
+ // We use selector, instead of id, to determine the key (signature for the mutation) because in some cases
3252
+ // repeated mutations can cause elements to be destroyed and then recreated as new DOM nodes
3253
+ // In those cases, IDs will change however the selector (which is relative to DOM xPath) remains the same
3254
+ var key = [value.selector, element, m.attributeName, names(m.addedNodes), names(m.removedNodes)].join();
3255
+ // Initialize an entry if it doesn't already exist
3256
+ history$1[key] = key in history$1 ? history$1[key] : [0];
3257
+ var h = history$1[key];
3258
+ // Lookup any pending nodes queued up for removal, and process them now if we suspended a mutation before
3259
+ if (inactive === false && h[0] >= 10 /* MutationSuspendThreshold */) {
3260
+ processNodeList(h[1], 2 /* ChildListRemove */, timer);
3261
+ }
3262
+ // Update the counter
3263
+ h[0] = inactive ? h[0] + 1 : 1;
3264
+ // Return updated mutation type based on if we have already hit the threshold or not
3265
+ if (h[0] === 10 /* MutationSuspendThreshold */) {
3266
+ // Store a reference to removedNodes so we can process them later
3267
+ // when we resume mutations again on user interactions
3268
+ h[1] = m.removedNodes;
3269
+ return "suspend" /* Suspend */;
3270
+ }
3271
+ else if (h[0] > 10 /* MutationSuspendThreshold */) {
3272
+ return "" /* Empty */;
3273
+ }
3274
+ }
3275
+ return m.type;
3276
+ }
3277
+ function names(nodes) {
3278
+ var output = [];
3279
+ for (var i = 0; nodes && i < nodes.length; i++) {
3280
+ output.push(nodes[i].nodeName);
3281
+ }
3282
+ return output.join();
3283
+ }
3284
+ function processNodeList(list, source, timer) {
3285
+ return __awaiter(this, void 0, void 0, function () {
3286
+ var length, i, state;
3287
+ return __generator(this, function (_a) {
3288
+ switch (_a.label) {
3289
+ case 0:
3290
+ length = list ? list.length : 0;
3291
+ i = 0;
3292
+ _a.label = 1;
3293
+ case 1:
3294
+ if (!(i < length)) return [3 /*break*/, 6];
3295
+ if (!(source === 1 /* ChildListAdd */)) return [3 /*break*/, 2];
3296
+ traverse(list[i], timer, source);
3297
+ return [3 /*break*/, 5];
3298
+ case 2:
3299
+ state = state$6(timer);
3300
+ if (!(state === 0 /* Wait */)) return [3 /*break*/, 4];
3301
+ return [4 /*yield*/, suspend$1(timer)];
3302
+ case 3:
3303
+ state = _a.sent();
3304
+ _a.label = 4;
3305
+ case 4:
3306
+ if (state === 2 /* Stop */) {
3307
+ return [3 /*break*/, 6];
3308
+ }
3309
+ processNode(list[i], source);
3310
+ _a.label = 5;
3311
+ case 5:
3312
+ i++;
3313
+ return [3 /*break*/, 1];
3314
+ case 6: return [2 /*return*/];
3315
+ }
3316
+ });
3317
+ });
3318
+ }
3319
+ function schedule(node) {
3320
+ // Only schedule manual trigger for this node if it's not already in the queue
3321
+ if (queue$1.indexOf(node) < 0) {
3322
+ queue$1.push(node);
3323
+ }
3324
+ // Cancel any previous trigger before scheduling a new one.
3325
+ // It's common for a webpage to call multiple synchronous "insertRule" / "deleteRule" calls.
3326
+ // And in those cases we do not wish to monitor changes multiple times for the same node.
3327
+ if (timeout$1) {
3328
+ clearTimeout(timeout$1);
3329
+ }
3330
+ timeout$1 = setTimeout(trigger, 33 /* LookAhead */);
3331
+ }
3332
+ function trigger() {
3333
+ for (var _i = 0, queue_1 = queue$1; _i < queue_1.length; _i++) {
3334
+ var node = queue_1[_i];
3335
+ generate(node, "characterData" /* CharacterData */);
3336
+ }
3337
+ queue$1 = [];
3338
+ }
3339
+ function generate(target, type) {
3340
+ measure(handle$1)([{
3341
+ addedNodes: [target],
3342
+ attributeName: null,
3343
+ attributeNamespace: null,
3344
+ nextSibling: null,
3345
+ oldValue: null,
3346
+ previousSibling: null,
3347
+ removedNodes: [],
3348
+ target: target,
3349
+ type: type
3350
+ }]);
3351
+ }
3352
+
3353
+ function target(evt) {
3354
+ var path = evt.composed && evt.composedPath ? evt.composedPath() : null;
3355
+ var node = (path && path.length > 0 ? path[0] : evt.target);
3356
+ active$2(); // Mark active periods of time so mutations can continue uninterrupted
3357
+ return node.nodeType === Node.DOCUMENT_NODE ? node.documentElement : node;
3358
+ }
3359
+ function link(node) {
3360
+ while (node && node !== document) {
3361
+ if (node.nodeType === Node.ELEMENT_NODE) {
3362
+ var element = node;
3363
+ if (element.tagName === "A") {
3364
+ return element;
3365
+ }
3366
+ }
3367
+ node = node.parentNode;
3368
+ }
3369
+ return null;
3370
+ }
3371
+ function metadata(node, event) {
3372
+ // If the node is null, we return a reserved value for id: 0. Valid assignment of id begins from 1+.
3373
+ var output = { id: 0, hash: null, selector: null, privacy: 2 /* Text */, node: node };
3374
+ if (node) {
3375
+ var value = get(node);
3376
+ if (value !== null) {
3377
+ output.id = value.id;
3378
+ output.hash = value.selector ? hash(value.selector) : null;
3379
+ output.selector = value.selector;
3380
+ output.privacy = value.metadata.privacy;
3381
+ if (value.region) {
3382
+ track$3(value.region, event);
3383
+ }
3384
+ }
3385
+ }
3386
+ return output;
3387
+ }
3388
+
3389
+ function encode$2 (type) {
3390
+ return __awaiter(this, void 0, void 0, function () {
3391
+ var t, tokens, i, entry, pTarget, i, entry, cTarget, r, u, i, entry, iTarget, s, startTarget, endTarget, i, entry, sTarget, i, entry, v;
3392
+ return __generator(this, function (_a) {
3393
+ t = time();
3394
+ tokens = [t, type];
3395
+ switch (type) {
3396
+ case 13 /* MouseDown */:
3397
+ case 14 /* MouseUp */:
3398
+ case 12 /* MouseMove */:
3399
+ case 15 /* MouseWheel */:
3400
+ case 16 /* DoubleClick */:
3401
+ case 17 /* TouchStart */:
3402
+ case 18 /* TouchEnd */:
3403
+ case 19 /* TouchMove */:
3404
+ case 20 /* TouchCancel */:
3405
+ for (i = 0; i < state$2.length; i++) {
3406
+ entry = state$2[i];
3407
+ pTarget = metadata(entry.data.target, entry.event);
3408
+ if (pTarget.id > 0) {
3409
+ tokens = [entry.time, entry.event];
3410
+ tokens.push(pTarget.id);
3411
+ tokens.push(entry.data.x);
3412
+ tokens.push(entry.data.y);
3413
+ queue(tokens);
3414
+ track$7(entry.event, entry.data.x, entry.data.y);
3415
+ }
3416
+ }
3417
+ reset$a();
3418
+ break;
3419
+ case 9 /* Click */:
3420
+ for (i = 0; i < state$4.length; i++) {
3421
+ entry = state$4[i];
3422
+ cTarget = metadata(entry.data.target, entry.event);
3423
+ tokens = [entry.time, entry.event];
3424
+ tokens.push(cTarget.id);
3425
+ tokens.push(entry.data.x);
3426
+ tokens.push(entry.data.y);
3427
+ tokens.push(entry.data.eX);
3428
+ tokens.push(entry.data.eY);
3429
+ tokens.push(entry.data.button);
3430
+ tokens.push(entry.data.reaction);
3431
+ tokens.push(entry.data.context);
3432
+ tokens.push(scrub(entry.data.text, "click", cTarget.privacy));
3433
+ tokens.push(entry.data.link);
3434
+ tokens.push(cTarget.hash);
3435
+ queue(tokens);
3436
+ track$1(entry.time, entry.event, cTarget.hash, entry.data.x, entry.data.y, entry.data.reaction, entry.data.context);
3437
+ }
3438
+ reset$c();
3439
+ break;
3440
+ case 11 /* Resize */:
3441
+ r = data$6;
3442
+ tokens.push(r.width);
3443
+ tokens.push(r.height);
3444
+ track$7(type, r.width, r.height);
3445
+ reset$9();
3446
+ queue(tokens);
3447
+ break;
3448
+ case 26 /* Unload */:
3449
+ u = data$4;
3450
+ tokens.push(u.name);
3451
+ reset$6();
3452
+ queue(tokens);
3453
+ break;
3454
+ case 27 /* Input */:
3455
+ for (i = 0; i < state$3.length; i++) {
3456
+ entry = state$3[i];
3457
+ iTarget = metadata(entry.data.target, entry.event);
3458
+ tokens = [entry.time, entry.event];
3459
+ tokens.push(iTarget.id);
3460
+ tokens.push(entry.data.value);
3461
+ queue(tokens);
3462
+ }
3463
+ reset$b();
3464
+ break;
3465
+ case 21 /* Selection */:
3466
+ s = data$5;
3467
+ if (s) {
3468
+ startTarget = metadata(s.start, type);
3469
+ endTarget = metadata(s.end, type);
3470
+ tokens.push(startTarget.id);
3471
+ tokens.push(s.startOffset);
3472
+ tokens.push(endTarget.id);
3473
+ tokens.push(s.endOffset);
3474
+ reset$7();
3475
+ queue(tokens);
3476
+ }
3477
+ break;
3478
+ case 10 /* Scroll */:
3479
+ for (i = 0; i < state$1.length; i++) {
3480
+ entry = state$1[i];
3481
+ sTarget = metadata(entry.data.target, entry.event);
3482
+ if (sTarget.id > 0) {
3483
+ tokens = [entry.time, entry.event];
3484
+ tokens.push(sTarget.id);
3485
+ tokens.push(entry.data.x);
3486
+ tokens.push(entry.data.y);
3487
+ queue(tokens);
3488
+ track$7(entry.event, entry.data.x, entry.data.y);
3489
+ }
3490
+ }
3491
+ reset$8();
3492
+ break;
3493
+ case 22 /* Timeline */:
3494
+ for (i = 0; i < updates$1.length; i++) {
3495
+ entry = updates$1[i];
3496
+ tokens = [entry.time, entry.event];
3497
+ tokens.push(entry.data.type);
3498
+ tokens.push(entry.data.hash);
3499
+ tokens.push(entry.data.x);
3500
+ tokens.push(entry.data.y);
3501
+ tokens.push(entry.data.reaction);
3502
+ tokens.push(entry.data.context);
3503
+ queue(tokens, false);
3504
+ }
3505
+ reset$4();
3506
+ break;
3507
+ case 28 /* Visibility */:
3508
+ v = data$3;
3509
+ tokens.push(v.visible);
3510
+ queue(tokens);
3511
+ visibility(t, v.visible);
3512
+ reset$5();
3513
+ break;
3514
+ }
3515
+ return [2 /*return*/];
3516
+ });
3517
+ });
3518
+ }
3519
+
3520
+ var state = [];
3521
+ var updates$1 = [];
3522
+ function start$b() {
3523
+ state = [];
3524
+ reset$4();
3525
+ }
3526
+ function reset$4() {
3527
+ updates$1 = [];
3528
+ }
3529
+ function track$1(time, event, hash, x, y, reaction, context) {
3530
+ if (reaction === void 0) { reaction = 1 /* True */; }
3531
+ if (context === void 0) { context = 0 /* Self */; }
3532
+ state.push({
3533
+ time: time,
3534
+ event: 22 /* Timeline */,
3535
+ data: {
3536
+ type: event,
3537
+ hash: hash,
3538
+ x: x,
3539
+ y: y,
3540
+ reaction: reaction,
3541
+ context: context
3542
+ }
3543
+ });
3544
+ // Since timeline only keeps the data for configured time, we still want to continue tracking these values
3545
+ // as part of the baseline. For instance, in a scenario where last scroll happened 5s ago.
3546
+ // We would still need to capture the last scroll position as part of the baseline event, even when timeline will be empty.
3547
+ track$7(event, x, y);
3548
+ }
3549
+ function compute$3() {
3550
+ var temp = [];
3551
+ updates$1 = [];
3552
+ var max = data$h.start + data$h.duration;
3553
+ var min = Math.max(max - 2000 /* TimelineSpan */, 0);
3554
+ for (var _i = 0, state_1 = state; _i < state_1.length; _i++) {
3555
+ var s = state_1[_i];
3556
+ if (s.time >= min) {
3557
+ if (s.time <= max) {
3558
+ updates$1.push(s);
3559
+ }
3560
+ temp.push(s);
3561
+ }
3562
+ }
3563
+ state = temp; // Drop events less than the min time
3564
+ encode$2(22 /* Timeline */);
3565
+ }
3566
+ function stop$a() {
3567
+ state = [];
3568
+ reset$4();
3569
+ }
3570
+
3571
+ var discoverBytes = 0;
3572
+ var playbackBytes = 0;
3573
+ var playback;
3574
+ var analysis;
3575
+ var timeout = null;
3576
+ var transit;
3577
+ var active$1;
3578
+ var queuedTime = 0;
3579
+ var track;
3580
+ function start$a() {
3581
+ active$1 = true;
3582
+ discoverBytes = 0;
3583
+ playbackBytes = 0;
3584
+ queuedTime = 0;
3585
+ playback = [];
3586
+ analysis = [];
3587
+ transit = {};
3588
+ track = null;
3589
+ }
3590
+ function queue(tokens, transmit) {
3591
+ if (transmit === void 0) { transmit = true; }
3592
+ if (active$1) {
3593
+ var now = time();
3594
+ var type = tokens.length > 1 ? tokens[1] : null;
3595
+ var event_1 = JSON.stringify(tokens);
3596
+ switch (type) {
3597
+ case 5 /* Discover */:
3598
+ discoverBytes += event_1.length;
3599
+ case 37 /* Box */:
3600
+ case 6 /* Mutation */:
3601
+ playbackBytes += event_1.length;
3602
+ playback.push(event_1);
3603
+ break;
3604
+ default:
3605
+ analysis.push(event_1);
3606
+ break;
3607
+ }
3608
+ // Following two checks are precautionary and act as a fail safe mechanism to get out of unexpected situations.
3609
+ // Check 1: If for any reason the upload hasn't happened after waiting for 2x the config.delay time,
3610
+ // reset the timer. This allows Clarity to attempt an upload again.
3611
+ var gap = delay();
3612
+ if (now - queuedTime > (gap * 2)) {
3613
+ clearTimeout(timeout);
3614
+ timeout = null;
3615
+ }
3616
+ // Transmit Check: When transmit is set to true (default), it indicates that we should schedule an upload
3617
+ // However, in certain scenarios - like metric calculation - which are triggered as part of an existing upload
3618
+ // We enrich the data going out with the existing upload. In these cases, call to upload comes with 'transmit' set to false.
3619
+ if (transmit && timeout === null) {
3620
+ if (type !== 25 /* Ping */) {
3621
+ reset$j();
3622
+ }
3623
+ timeout = setTimeout(upload, gap);
3624
+ queuedTime = now;
3625
+ check$3(playbackBytes);
3626
+ }
3627
+ }
3628
+ }
3629
+ function stop$9() {
3630
+ clearTimeout(timeout);
3631
+ upload(true);
3632
+ discoverBytes = 0;
3633
+ playbackBytes = 0;
3634
+ queuedTime = 0;
3635
+ playback = [];
3636
+ analysis = [];
3637
+ transit = {};
3638
+ track = null;
3639
+ active$1 = false;
3640
+ }
3641
+ function upload(final) {
3642
+ if (final === void 0) { final = false; }
3643
+ return __awaiter(this, void 0, void 0, function () {
3644
+ var sendPlaybackBytes, last, e, a, p, encoded, payload, zipped, _a;
3645
+ return __generator(this, function (_b) {
3646
+ switch (_b.label) {
3647
+ case 0:
3648
+ timeout = null;
3649
+ sendPlaybackBytes = config$1.lean === false && playbackBytes > 0 && (playbackBytes < 1048576 /* MaxFirstPayloadBytes */ || data$h.sequence > 0);
3650
+ if (sendPlaybackBytes) {
3651
+ max(1 /* Playback */, 1 /* True */);
3652
+ }
3653
+ // CAUTION: Ensure "transmit" is set to false in the queue function for following events
3654
+ // Otherwise you run a risk of infinite loop.
3655
+ compute$4();
3656
+ compute$3();
3657
+ compute$7();
3658
+ last = final === true;
3659
+ e = JSON.stringify(envelope(last));
3660
+ a = "[" + analysis.join() + "]";
3661
+ p = sendPlaybackBytes ? "[" + playback.join() + "]" : "" /* Empty */;
3662
+ encoded = { e: e, a: a, p: p };
3663
+ payload = stringify(encoded);
3664
+ if (!last) return [3 /*break*/, 1];
3665
+ _a = null;
3666
+ return [3 /*break*/, 3];
3667
+ case 1: return [4 /*yield*/, compress(payload)];
3668
+ case 2:
3669
+ _a = _b.sent();
3670
+ _b.label = 3;
3671
+ case 3:
3672
+ zipped = _a;
3673
+ sum(2 /* TotalBytes */, zipped ? zipped.length : payload.length);
3674
+ send(payload, zipped, data$h.sequence, last);
3675
+ // Clear out events now that payload has been dispatched
3676
+ analysis = [];
3677
+ if (sendPlaybackBytes) {
3678
+ playback = [];
3679
+ playbackBytes = 0;
3680
+ discoverBytes = 0;
3681
+ }
3682
+ return [2 /*return*/];
3683
+ }
3684
+ });
3685
+ });
3686
+ }
3687
+ function stringify(encoded) {
3688
+ return encoded.p.length > 0 ? "{\"e\":" + encoded.e + ",\"a\":" + encoded.a + ",\"p\":" + encoded.p + "}" : "{\"e\":" + encoded.e + ",\"a\":" + encoded.a + "}";
3689
+ }
3690
+ function send(payload, zipped, sequence, beacon) {
3691
+ if (beacon === void 0) { beacon = false; }
3692
+ // Upload data if a valid URL is defined in the config
3693
+ if (typeof config$1.upload === "string" /* String */) {
3694
+ var url = config$1.upload;
3695
+ var dispatched = false;
3696
+ // If it's the last payload, attempt to upload using sendBeacon first.
3697
+ // The advantage to using sendBeacon is that browser can decide to upload asynchronously, improving chances of success
3698
+ // However, we don't want to rely on it for every payload, since we have no ability to retry if the upload failed.
3699
+ // Also, in case of sendBeacon, we do not have a way to alter HTTP headers and therefore can't send compressed payload
3700
+ if (beacon && "sendBeacon" in navigator) {
3701
+ dispatched = navigator.sendBeacon(url, payload);
3702
+ if (dispatched) {
3703
+ done(sequence);
3704
+ }
3705
+ }
3706
+ // Before initiating XHR upload, we check if the data has already been uploaded using sendBeacon
3707
+ // There are two cases when dispatched could still be false:
3708
+ // a) It's not the last payload, and therefore we didn't attempt sending sendBeacon
3709
+ // b) It's the last payload, however, we failed to queue sendBeacon call and need to now fall back to XHR.
3710
+ // E.g. if data is over 64KB, several user agents (like Chrome) will reject to queue the sendBeacon call.
3711
+ if (dispatched === false) {
3712
+ // While tracking payload for retry, we only track string value of the payload to err on the safe side
3713
+ // Not all browsers support compression API and the support for it in supported browsers is still experimental
3714
+ if (sequence in transit) {
3715
+ transit[sequence].attempts++;
3716
+ }
3717
+ else {
3718
+ transit[sequence] = { data: payload, attempts: 1 };
3719
+ }
3720
+ var xhr_1 = new XMLHttpRequest();
3721
+ xhr_1.open("POST", url);
3722
+ if (sequence !== null) {
3723
+ xhr_1.onreadystatechange = function () { measure(check$2)(xhr_1, sequence); };
3724
+ }
3725
+ xhr_1.withCredentials = true;
3726
+ if (zipped) {
3727
+ // If we do have valid compressed array, send it with appropriate HTTP headers so server can decode it appropriately
3728
+ xhr_1.setRequestHeader("Accept" /* Accept */, "application/x-clarity-gzip" /* ClarityGzip */);
3729
+ xhr_1.send(zipped);
3730
+ }
3731
+ else {
3732
+ // In all other cases, continue sending string back to the server
3733
+ xhr_1.send(payload);
3734
+ }
3735
+ }
3736
+ }
3737
+ else if (config$1.upload) {
3738
+ var callback = config$1.upload;
3739
+ callback(payload);
3740
+ done(sequence);
3741
+ }
3742
+ }
3743
+ function check$2(xhr, sequence) {
3744
+ var transitData = transit[sequence];
3745
+ if (xhr && xhr.readyState === 4 /* Done */ && transitData) {
3746
+ // Attempt send payload again (as configured in settings) if we do not receive a success (2XX) response code back from the server
3747
+ if ((xhr.status < 200 || xhr.status > 208) && transitData.attempts <= 1 /* RetryLimit */) {
3748
+ // We re-attempt in all cases except when server explicitly rejects our request with 4XX error
3749
+ if (xhr.status >= 400 && xhr.status < 500) {
3750
+ // In case of a 4XX response from the server, we bail out instead of trying again
3751
+ trigger$1(6 /* Server */);
3752
+ }
3753
+ else {
3754
+ // Browser will send status = 0 when it refuses to put network request over the wire
3755
+ // This could happen for several reasons, couple of known ones are:
3756
+ // 1: Browsers block upload because of content security policy violation
3757
+ // 2: Safari will terminate pending XHR requests with status code 0 if the user navigates away from the page
3758
+ // In any case, we switch the upload URL to fallback configuration (if available) before re-trying one more time
3759
+ if (xhr.status === 0) {
3760
+ config$1.upload = config$1.fallback ? config$1.fallback : config$1.upload;
3761
+ }
3762
+ // In all other cases, re-attempt sending the same data
3763
+ // For retry we always fallback to string payload, even though we may have attempted
3764
+ // sending zipped payload earlier
3765
+ send(transitData.data, null, sequence);
3766
+ }
3767
+ }
3768
+ else {
3769
+ track = { sequence: sequence, attempts: transitData.attempts, status: xhr.status };
3770
+ // Send back an event only if we were not successful in our first attempt
3771
+ if (transitData.attempts > 1) {
3772
+ encode$1(2 /* Upload */);
3773
+ }
3774
+ // Handle response if it was a 200 response with a valid body
3775
+ if (xhr.status === 200 && xhr.responseText) {
3776
+ response(xhr.responseText);
3777
+ }
3778
+ // If we exhausted our retries then trigger Clarity's shutdown for this page since the data will be incomplete
3779
+ if (xhr.status === 0) {
3780
+ // And, right before we terminate the session, we will attempt one last time to see if we can use
3781
+ // different transport option (sendBeacon vs. XHR) to get this data to the server for analysis purposes
3782
+ send(transitData.data, null, sequence, true);
3783
+ trigger$1(3 /* Retry */);
3784
+ }
3785
+ // Signal that this request completed successfully
3786
+ if (xhr.status >= 200 && xhr.status <= 208) {
3787
+ done(sequence);
3788
+ }
3789
+ // Stop tracking this payload now that it's all done
3790
+ delete transit[sequence];
3791
+ }
3792
+ }
3793
+ }
3794
+ function done(sequence) {
3795
+ // If we everything went successfully, and it is the first sequence, save this session for future reference
3796
+ if (sequence === 1) {
3797
+ save();
3798
+ }
3799
+ }
3800
+ function delay() {
3801
+ // Progressively increase delay as we continue to send more payloads from the client to the server
3802
+ // If we are not uploading data to a server, and instead invoking UploadCallback, in that case keep returning configured value
3803
+ var gap = config$1.lean === false && discoverBytes > 0 ? 100 /* MinUploadDelay */ : data$h.sequence * config$1.delay;
3804
+ return typeof config$1.upload === "string" /* String */ ? Math.max(Math.min(gap, 30000 /* MaxUploadDelay */), 100 /* MinUploadDelay */) : config$1.delay;
3805
+ }
3806
+ function response(payload) {
3807
+ var key = payload && payload.length > 0 ? payload.split(" ")[0] : "" /* Empty */;
3808
+ switch (key) {
3809
+ case "END" /* End */:
3810
+ // Clear out session storage and end the session so we can start fresh the next time
3811
+ trigger$1(6 /* Server */);
3812
+ break;
3813
+ case "UPGRADE" /* Upgrade */:
3814
+ // Upgrade current session to send back playback information
3815
+ upgrade("Auto" /* Auto */);
3816
+ break;
3817
+ }
3818
+ }
3819
+
3820
+ function encode$1 (event) {
3821
+ var t = time();
3822
+ var tokens = [t, event];
3823
+ switch (event) {
3824
+ case 4 /* Baseline */:
3825
+ var b = state$7;
3826
+ if (b) {
3827
+ tokens = [b.time, b.event];
3828
+ tokens.push(b.data.visible);
3829
+ tokens.push(b.data.docWidth);
3830
+ tokens.push(b.data.docHeight);
3831
+ tokens.push(b.data.screenWidth);
3832
+ tokens.push(b.data.screenHeight);
3833
+ tokens.push(b.data.scrollX);
3834
+ tokens.push(b.data.scrollY);
3835
+ tokens.push(b.data.pointerX);
3836
+ tokens.push(b.data.pointerY);
3837
+ tokens.push(b.data.activityTime);
3838
+ queue(tokens, false);
3839
+ }
3840
+ reset$n();
3841
+ break;
3842
+ case 25 /* Ping */:
3843
+ tokens.push(data$e.gap);
3844
+ queue(tokens);
3845
+ break;
3846
+ case 35 /* Limit */:
3847
+ tokens.push(data$g.check);
3848
+ queue(tokens, false);
3849
+ break;
3850
+ case 3 /* Upgrade */:
3851
+ tokens.push(data$c.key);
3852
+ queue(tokens);
3853
+ break;
3854
+ case 2 /* Upload */:
3855
+ tokens.push(track.sequence);
3856
+ tokens.push(track.attempts);
3857
+ tokens.push(track.status);
3858
+ queue(tokens, false);
3859
+ break;
3860
+ case 24 /* Custom */:
3861
+ tokens.push(data$k.key);
3862
+ tokens.push(data$k.value);
3863
+ queue(tokens);
3864
+ break;
3865
+ case 34 /* Variable */:
3866
+ var variableKeys = Object.keys(data$j);
3867
+ if (variableKeys.length > 0) {
3868
+ for (var _i = 0, variableKeys_1 = variableKeys; _i < variableKeys_1.length; _i++) {
3869
+ var v = variableKeys_1[_i];
3870
+ tokens.push(v);
3871
+ tokens.push(data$j[v]);
3872
+ }
3873
+ reset$m();
3874
+ queue(tokens, false);
3875
+ }
3876
+ break;
3877
+ case 0 /* Metric */:
3878
+ var metricKeys = Object.keys(updates);
3879
+ if (metricKeys.length > 0) {
3880
+ for (var _a = 0, metricKeys_1 = metricKeys; _a < metricKeys_1.length; _a++) {
3881
+ var m = metricKeys_1[_a];
3882
+ var key = parseInt(m, 10);
3883
+ tokens.push(key);
3884
+ // For computation, we need microseconds precision that performance.now() API offers
3885
+ // However, for data over the wire, we round it off to milliseconds precision.
3886
+ tokens.push(Math.round(updates[m]));
3887
+ }
3888
+ reset$3();
3889
+ queue(tokens, false);
3890
+ }
3891
+ break;
3892
+ case 1 /* Dimension */:
3893
+ var dimensionKeys = Object.keys(updates$3);
3894
+ if (dimensionKeys.length > 0) {
3895
+ for (var _b = 0, dimensionKeys_1 = dimensionKeys; _b < dimensionKeys_1.length; _b++) {
3896
+ var d = dimensionKeys_1[_b];
3897
+ var key = parseInt(d, 10);
3898
+ tokens.push(key);
3899
+ tokens.push(updates$3[d]);
3900
+ }
3901
+ reset$k();
3902
+ queue(tokens, false);
3903
+ }
3904
+ break;
3905
+ case 36 /* Summary */:
3906
+ var eventKeys = Object.keys(data$d);
3907
+ if (eventKeys.length > 0) {
3908
+ for (var _c = 0, eventKeys_1 = eventKeys; _c < eventKeys_1.length; _c++) {
3909
+ var e = eventKeys_1[_c];
3910
+ var key = parseInt(e, 10);
3911
+ tokens.push(key);
3912
+ tokens.push([].concat.apply([], data$d[e]));
3913
+ }
3914
+ reset$i();
3915
+ queue(tokens, false);
3916
+ }
3917
+ break;
3918
+ }
3919
+ }
3920
+
3921
+ var data$2 = null;
3922
+ var updates = null;
3923
+ function start$9() {
3924
+ data$2 = {};
3925
+ updates = {};
3926
+ count$1(5 /* InvokeCount */);
3927
+ }
3928
+ function stop$8() {
3929
+ data$2 = {};
3930
+ updates = {};
3931
+ }
3932
+ function count$1(metric, increment) {
3933
+ if (increment === void 0) { increment = 1; }
3934
+ if (!(metric in data$2)) {
3935
+ data$2[metric] = 0;
3936
+ }
3937
+ if (!(metric in updates)) {
3938
+ updates[metric] = 0;
3939
+ }
3940
+ data$2[metric] += increment;
3941
+ updates[metric] += increment;
3942
+ }
3943
+ function sum(metric, value) {
3944
+ if (value !== null) {
3945
+ if (!(metric in data$2)) {
3946
+ data$2[metric] = 0;
3947
+ }
3948
+ if (!(metric in updates)) {
3949
+ updates[metric] = 0;
3950
+ }
3951
+ data$2[metric] += value;
3952
+ updates[metric] += value;
3953
+ }
3954
+ }
3955
+ function max(metric, value) {
3956
+ // Ensure that we do not process null or NaN values
3957
+ if (value !== null && isNaN(value) === false) {
3958
+ if (!(metric in data$2)) {
3959
+ data$2[metric] = 0;
3960
+ }
3961
+ if (value > data$2[metric] || data$2[metric] === 0) {
3962
+ updates[metric] = value;
3963
+ data$2[metric] = value;
3964
+ }
3965
+ }
3966
+ }
3967
+ function compute$2() {
3968
+ encode$1(0 /* Metric */);
3969
+ }
3970
+ function reset$3() {
3971
+ updates = {};
3972
+ }
3973
+
3974
+ // tslint:disable-next-line: ban-types
3975
+ function measure (method) {
3976
+ return function () {
3977
+ var start = performance.now();
3978
+ method.apply(this, arguments);
3979
+ var duration = performance.now() - start;
3980
+ sum(4 /* TotalCost */, duration);
3981
+ if (duration > 30 /* LongTask */) {
3982
+ count$1(7 /* LongTaskCount */);
3983
+ max(6 /* ThreadBlockedTime */, duration);
3984
+ }
3985
+ };
3986
+ }
3987
+
3988
+ var bindings = [];
3989
+ function bind(target, event, listener, capture) {
3990
+ if (capture === void 0) { capture = false; }
3991
+ listener = measure(listener);
3992
+ // Wrapping following lines inside try / catch to cover edge cases where we might try to access an inaccessible element.
3993
+ // E.g. Iframe may start off as same-origin but later turn into cross-origin, and the following lines will throw an exception.
3994
+ try {
3995
+ target.addEventListener(event, listener, capture);
3996
+ bindings.push({ event: event, target: target, listener: listener, capture: capture });
3997
+ }
3998
+ catch ( /* do nothing */_a) { /* do nothing */ }
3999
+ }
4000
+ function reset$2() {
4001
+ // Walk through existing list of bindings and remove them all
4002
+ for (var _i = 0, bindings_1 = bindings; _i < bindings_1.length; _i++) {
4003
+ var binding = bindings_1[_i];
4004
+ // Wrapping inside try / catch to avoid situations where the element may be destroyed before we get a chance to unbind
4005
+ try {
4006
+ binding.target.removeEventListener(binding.event, binding.listener, binding.capture);
4007
+ }
4008
+ catch ( /* do nothing */_a) { /* do nothing */ }
4009
+ }
4010
+ bindings = [];
4011
+ }
4012
+
4013
+ var pushState = null;
4014
+ var replaceState = null;
4015
+ var url = null;
4016
+ var count = 0;
4017
+ function start$8() {
4018
+ url = getCurrentUrl();
4019
+ count = 0;
4020
+ bind(window, "popstate", compute$1);
4021
+ // Add a proxy to history.pushState function
4022
+ if (pushState === null) {
4023
+ pushState = history.pushState;
4024
+ }
4025
+ history.pushState = function () {
4026
+ if (check$1()) {
4027
+ pushState.apply(this, arguments);
4028
+ compute$1();
4029
+ }
4030
+ };
4031
+ // Add a proxy to history.replaceState function
4032
+ if (replaceState === null) {
4033
+ replaceState = history.replaceState;
4034
+ }
4035
+ history.replaceState = function () {
4036
+ if (check$1()) {
4037
+ replaceState.apply(this, arguments);
4038
+ compute$1();
4039
+ }
4040
+ };
4041
+ }
4042
+ function check$1() {
4043
+ if (count++ > 20 /* CallStackDepth */) {
4044
+ log(4 /* CallStackDepth */, 0 /* Info */);
4045
+ return false;
4046
+ }
4047
+ return true;
4048
+ }
4049
+ function compute$1() {
4050
+ if (url !== getCurrentUrl() && count <= 20 /* CallStackDepth */) {
4051
+ stop();
4052
+ window.setTimeout(start, 250 /* RestartDelay */);
4053
+ }
4054
+ }
4055
+ function getCurrentUrl() {
4056
+ return location.href ? location.href.replace(location.hash, "" /* Empty */) : location.href;
4057
+ }
4058
+ function stop$7() {
4059
+ // Restore original function definition of history.pushState
4060
+ if (pushState !== null) {
4061
+ history.pushState = pushState;
4062
+ pushState = null;
4063
+ }
4064
+ // Restore original function definition of history.replaceState
4065
+ if (replaceState !== null) {
4066
+ history.replaceState = replaceState;
4067
+ replaceState = null;
4068
+ }
4069
+ url = null;
4070
+ count = 0;
4071
+ }
4072
+
4073
+ var status = false;
4074
+ function start$7() {
4075
+ status = true;
4076
+ start$E();
4077
+ reset$h();
4078
+ reset$2();
4079
+ reset$l();
4080
+ start$8();
4081
+ }
4082
+ function stop$6() {
4083
+ stop$7();
4084
+ reset$l();
4085
+ reset$2();
4086
+ reset$h();
4087
+ stop$B();
4088
+ status = false;
4089
+ }
4090
+ function active() {
4091
+ return status;
4092
+ }
4093
+ function check() {
4094
+ try {
4095
+ return status === false &&
4096
+ typeof Promise !== "undefined" &&
4097
+ window["MutationObserver"] &&
4098
+ document["createTreeWalker"] &&
4099
+ "now" in Date &&
4100
+ "now" in performance &&
4101
+ typeof WeakMap !== "undefined";
4102
+ }
4103
+ catch (ex) {
4104
+ return false;
4105
+ }
4106
+ }
4107
+ function config(override) {
4108
+ // Process custom configuration overrides, if available
4109
+ if (override === null || status) {
4110
+ return false;
4111
+ }
4112
+ for (var key in override) {
4113
+ if (key in config$1) {
4114
+ config$1[key] = override[key];
4115
+ }
4116
+ }
4117
+ return true;
4118
+ }
4119
+ // Suspend ends the current Clarity instance after a configured timeout period
4120
+ // The way it differs from the "end" call is that it starts listening to
4121
+ // user interaction events as soon as it terminates existing clarity instance.
4122
+ // On the next interaction, it automatically starts another instance under a different page id
4123
+ // E.g. if configured timeout is 10m, and user stays inactive for an hour.
4124
+ // In this case, we will suspend clarity after 10m of inactivity and after another 50m when user interacts again
4125
+ // Clarity will restart and start another instance seamlessly. Effectively not missing any active time, but also
4126
+ // not holding the session during inactive time periods.
4127
+ function suspend() {
4128
+ if (status) {
4129
+ event("clarity" /* Clarity */, "suspend" /* Suspend */);
4130
+ stop();
4131
+ ["document", "touchstart"].forEach(function (x) { return bind(document, x, restart); });
4132
+ ["resize", "scroll", "pageshow"].forEach(function (x) { return bind(window, x, restart); });
4133
+ }
4134
+ }
4135
+ function restart() {
4136
+ start();
4137
+ event("clarity" /* Clarity */, "restart" /* Restart */);
4138
+ }
4139
+
4140
+ function start$6() {
4141
+ start$p();
4142
+ start$s();
4143
+ start$o();
4144
+ }
4145
+ function stop$5() {
4146
+ stop$p();
4147
+ stop$n();
4148
+ }
4149
+
4150
+ var diagnostic = /*#__PURE__*/Object.freeze({
4151
+ __proto__: null,
4152
+ start: start$6,
4153
+ stop: stop$5
4154
+ });
4155
+
4156
+ function start$5() {
4157
+ schedule$1(discover, 1 /* High */).then(function () {
4158
+ measure(compute$6)();
4159
+ measure(compute$4)();
4160
+ });
4161
+ }
4162
+ function discover() {
4163
+ return __awaiter(this, void 0, void 0, function () {
4164
+ var ts, timer;
4165
+ return __generator(this, function (_a) {
4166
+ switch (_a.label) {
4167
+ case 0:
4168
+ ts = time();
4169
+ timer = { id: id(), cost: 3 /* LayoutCost */ };
4170
+ start$t(timer);
4171
+ return [4 /*yield*/, traverse(document, timer, 0 /* Discover */)];
4172
+ case 1:
4173
+ _a.sent();
4174
+ return [4 /*yield*/, encode$4(5 /* Discover */, timer, ts)];
4175
+ case 2:
4176
+ _a.sent();
4177
+ stop$q(timer);
4178
+ return [2 /*return*/];
4179
+ }
4180
+ });
4181
+ });
4182
+ }
4183
+
4184
+ function start$4() {
4185
+ // The order below is important
4186
+ // and is determined by interdependencies of modules
4187
+ start$r();
4188
+ start$m();
4189
+ start$n();
4190
+ start$c();
4191
+ start$5();
4192
+ start$q();
4193
+ }
4194
+ function stop$4() {
4195
+ stop$l();
4196
+ stop$m();
4197
+ stop$b();
4198
+ stop$o();
4199
+ end();
4200
+ }
4201
+
4202
+ var layout = /*#__PURE__*/Object.freeze({
4203
+ __proto__: null,
4204
+ start: start$4,
4205
+ stop: stop$4
4206
+ });
4207
+
4208
+ var data$1 = null;
4209
+ function reset$1() {
4210
+ data$1 = null;
4211
+ }
4212
+ function compute(entry) {
4213
+ data$1 = {
4214
+ fetchStart: Math.round(entry.fetchStart),
4215
+ connectStart: Math.round(entry.connectStart),
4216
+ connectEnd: Math.round(entry.connectEnd),
4217
+ requestStart: Math.round(entry.requestStart),
4218
+ responseStart: Math.round(entry.responseStart),
4219
+ responseEnd: Math.round(entry.responseEnd),
4220
+ domInteractive: Math.round(entry.domInteractive),
4221
+ domComplete: Math.round(entry.domComplete),
4222
+ loadEventStart: Math.round(entry.loadEventStart),
4223
+ loadEventEnd: Math.round(entry.loadEventEnd),
4224
+ redirectCount: Math.round(entry.redirectCount),
4225
+ size: entry.transferSize ? entry.transferSize : 0,
4226
+ type: entry.type,
4227
+ protocol: entry.nextHopProtocol,
4228
+ encodedSize: entry.encodedBodySize ? entry.encodedBodySize : 0,
4229
+ decodedSize: entry.decodedBodySize ? entry.decodedBodySize : 0
4230
+ };
4231
+ encode(29 /* Navigation */);
4232
+ }
4233
+
4234
+ function encode (type) {
4235
+ return __awaiter(this, void 0, void 0, function () {
4236
+ var t, tokens;
4237
+ return __generator(this, function (_a) {
4238
+ t = time();
4239
+ tokens = [t, type];
4240
+ switch (type) {
4241
+ case 30 /* Connection */:
4242
+ tokens.push(data.downlink);
4243
+ tokens.push(data.rtt);
4244
+ tokens.push(data.saveData);
4245
+ tokens.push(data.type);
4246
+ reset();
4247
+ queue(tokens, false);
4248
+ break;
4249
+ case 29 /* Navigation */:
4250
+ tokens.push(data$1.fetchStart);
4251
+ tokens.push(data$1.connectStart);
4252
+ tokens.push(data$1.connectEnd);
4253
+ tokens.push(data$1.requestStart);
4254
+ tokens.push(data$1.responseStart);
4255
+ tokens.push(data$1.responseEnd);
4256
+ tokens.push(data$1.domInteractive);
4257
+ tokens.push(data$1.domComplete);
4258
+ tokens.push(data$1.loadEventStart);
4259
+ tokens.push(data$1.loadEventEnd);
4260
+ tokens.push(data$1.redirectCount);
4261
+ tokens.push(data$1.size);
4262
+ tokens.push(data$1.type);
4263
+ tokens.push(data$1.protocol);
4264
+ tokens.push(data$1.encodedSize);
4265
+ tokens.push(data$1.decodedSize);
4266
+ reset$1();
4267
+ queue(tokens, false);
4268
+ break;
4269
+ }
4270
+ return [2 /*return*/];
4271
+ });
4272
+ });
4273
+ }
4274
+
4275
+ // Reference: https://wicg.github.io/netinfo/
4276
+ var data;
4277
+ function start$3() {
4278
+ // Check if the client supports Navigator.Connection: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
4279
+ // This is an experimental API so we go a bit deeper in our check and ensure that values returned are valid
4280
+ if (navigator &&
4281
+ "connection" in navigator &&
4282
+ "downlink" in navigator["connection"] &&
4283
+ typeof navigator["connection"]["downlink"] === "number") {
4284
+ navigator["connection"].addEventListener("change", recompute);
4285
+ recompute();
4286
+ }
4287
+ }
4288
+ function recompute() {
4289
+ var connection = navigator["connection"];
4290
+ data = {
4291
+ downlink: connection.downlink,
4292
+ rtt: connection.rtt,
4293
+ saveData: connection.saveData ? 1 /* True */ : 0 /* False */,
4294
+ type: connection.effectiveType
4295
+ };
4296
+ encode(30 /* Connection */);
4297
+ }
4298
+ function reset() {
4299
+ data = null;
4300
+ }
4301
+ function stop$3() {
4302
+ reset();
4303
+ }
4304
+
4305
+ var observer;
4306
+ var types = ["navigation" /* Navigation */, "resource" /* Resource */, "longtask" /* LongTask */, "first-input" /* FID */, "layout-shift" /* CLS */, "largest-contentful-paint" /* LCP */];
4307
+ function start$2() {
4308
+ // Check the browser support performance observer as a pre-requisite for any performance measurement
4309
+ if (window["PerformanceObserver"] && PerformanceObserver.supportedEntryTypes) {
4310
+ // Start monitoring performance data after page has finished loading.
4311
+ // If the document.readyState is not yet complete, we intentionally call observe using a setTimeout.
4312
+ // This allows us to capture loadEventEnd on navigation timeline.
4313
+ if (document.readyState !== "complete") {
4314
+ bind(window, "load", setTimeout.bind(this, observe, 0));
4315
+ }
4316
+ else {
4317
+ observe();
4318
+ }
4319
+ }
4320
+ else {
4321
+ log(3 /* PerformanceObserver */, 0 /* Info */);
4322
+ }
4323
+ }
4324
+ function observe() {
4325
+ // Some browsers will throw an error for unsupported entryType, e.g. "layout-shift"
4326
+ // In those cases, we log it as a warning and continue with rest of the Clarity processing
4327
+ try {
4328
+ if (observer) {
4329
+ observer.disconnect();
4330
+ }
4331
+ observer = new PerformanceObserver(measure(handle));
4332
+ // Reference: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/observe
4333
+ // "buffered" flag indicates whether buffered entries should be queued into the observer's buffer.
4334
+ // It must only be used only with the "type" option, and cannot be used with entryTypes.
4335
+ // This is why we need to individually "observe" each supported type
4336
+ for (var _i = 0, types_1 = types; _i < types_1.length; _i++) {
4337
+ var x = types_1[_i];
4338
+ if (PerformanceObserver.supportedEntryTypes.indexOf(x) >= 0) {
4339
+ // Initialize CLS with a value of zero. It's possible (and recommended) for sites to not have any cumulative layout shift.
4340
+ // In those cases, we want to still initialize the metric in Clarity
4341
+ if (x === "layout-shift" /* CLS */) {
4342
+ sum(9 /* CumulativeLayoutShift */, 0);
4343
+ }
4344
+ observer.observe({ type: x, buffered: true });
4345
+ }
4346
+ }
4347
+ }
4348
+ catch (_a) {
4349
+ log(3 /* PerformanceObserver */, 1 /* Warning */);
4350
+ }
4351
+ }
4352
+ function handle(entries) {
4353
+ process(entries.getEntries());
4354
+ }
4355
+ function process(entries) {
4356
+ var visible = "visibilityState" in document ? document.visibilityState === "visible" : true;
4357
+ for (var i = 0; i < entries.length; i++) {
4358
+ var entry = entries[i];
4359
+ switch (entry.entryType) {
4360
+ case "navigation" /* Navigation */:
4361
+ compute(entry);
4362
+ break;
4363
+ case "resource" /* Resource */:
4364
+ log$1(4 /* NetworkHosts */, host(entry.name));
4365
+ break;
4366
+ case "longtask" /* LongTask */:
4367
+ count$1(7 /* LongTaskCount */);
4368
+ break;
4369
+ case "first-input" /* FID */:
4370
+ if (visible) {
4371
+ max(10 /* FirstInputDelay */, entry["processingStart"] - entry.startTime);
4372
+ }
4373
+ break;
4374
+ case "layout-shift" /* CLS */:
4375
+ // Scale the value to avoid sending back floating point number
4376
+ if (visible && !entry["hadRecentInput"]) {
4377
+ sum(9 /* CumulativeLayoutShift */, entry["value"] * 1000);
4378
+ }
4379
+ break;
4380
+ case "largest-contentful-paint" /* LCP */:
4381
+ if (visible) {
4382
+ max(8 /* LargestPaint */, entry.startTime);
4383
+ }
4384
+ break;
4385
+ }
4386
+ }
4387
+ }
4388
+ function stop$2() {
4389
+ if (observer) {
4390
+ observer.disconnect();
4391
+ }
4392
+ observer = null;
4393
+ }
4394
+ function host(url) {
4395
+ var a = document.createElement("a");
4396
+ a.href = url;
4397
+ return a.hostname;
4398
+ }
4399
+
4400
+ function start$1() {
4401
+ reset$1();
4402
+ start$3();
4403
+ start$2();
4404
+ }
4405
+ function stop$1() {
4406
+ stop$2();
4407
+ stop$3();
4408
+ reset$1();
4409
+ }
4410
+
4411
+ var performance$1 = /*#__PURE__*/Object.freeze({
4412
+ __proto__: null,
4413
+ start: start$1,
4414
+ stop: stop$1
4415
+ });
4416
+
4417
+ var modules = [diagnostic, layout, interaction, performance$1];
4418
+ function start(config$1) {
4419
+ if (config$1 === void 0) { config$1 = null; }
4420
+ // Check that browser supports required APIs and we do not attempt to start Clarity multiple times
4421
+ if (check()) {
4422
+ config(config$1);
4423
+ start$7();
4424
+ start$u();
4425
+ modules.forEach(function (x) { return measure(x.start)(); });
4426
+ }
4427
+ }
4428
+ // By default Clarity is asynchronous and will yield by looking for requestIdleCallback.
4429
+ // However, there can still be situations with single page apps where a user action can result
4430
+ // in the whole DOM being destroyed and reconstructed. While Clarity will perform favorably out of the box,
4431
+ // we do allow external clients to manually pause Clarity for that short burst of time and minimize
4432
+ // performance impact even further. For reference, we are talking single digit milliseconds optimization here, not seconds.
4433
+ function pause() {
4434
+ if (active()) {
4435
+ event("clarity" /* Clarity */, "pause" /* Pause */);
4436
+ pause$1();
4437
+ }
4438
+ }
4439
+ // This is how external clients can get out of pause state, and resume Clarity to continue monitoring the page
4440
+ function resume() {
4441
+ if (active()) {
4442
+ resume$1();
4443
+ event("clarity" /* Clarity */, "resume" /* Resume */);
4444
+ }
4445
+ }
4446
+ function stop() {
4447
+ if (active()) {
4448
+ // Stop modules in the reverse order of their initialization
4449
+ modules.slice().reverse().forEach(function (x) { return measure(x.stop)(); });
4450
+ stop$r();
4451
+ stop$6();
4452
+ }
4453
+ }
4454
+
4455
+ var clarity = /*#__PURE__*/Object.freeze({
4456
+ __proto__: null,
4457
+ version: version$1,
4458
+ start: start,
4459
+ pause: pause,
4460
+ resume: resume,
4461
+ stop: stop,
4462
+ consent: consent,
4463
+ event: event,
4464
+ identify: identify,
4465
+ set: set,
4466
+ upgrade: upgrade,
4467
+ metadata: metadata$2
4468
+ });
4469
+
4470
+ var helper = { hash: hash, selector: selector };
4471
+ var version = version$1;
4472
+
4473
+ export { clarity, helper, version };