@levo-so/insights 0.1.65 → 0.1.71

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.
@@ -0,0 +1,857 @@
1
+ import { map as X, computed as de, atom as E } from "nanostores";
2
+ import { onUserActivity as xe } from "@analytics/activity-utils";
3
+ const W = X({
4
+ workspace: null,
5
+ page_id: null,
6
+ site_id: null,
7
+ debug: !1
8
+ }), Z = () => W.get(), Wt = (e) => W.set({ ...Z(), ...e }), $t = (e, t) => W.setKey(e, t), _e = ({
9
+ deviceToken: e,
10
+ sessionToken: t,
11
+ mode: n
12
+ }) => {
13
+ const s = {};
14
+ return n === "direct" && (e && (s["Levo-Audience-Device"] = e), t && (s["Levo-Audience-Session"] = t)), s;
15
+ }, _ = {
16
+ /** Legacy: Lock key for identify operation (no longer used internally) */
17
+ identify: "lock:lv_aud_identify",
18
+ /** Key for tracking open tab count */
19
+ open_tabs: "lv_insights_ot",
20
+ /** Key for current tab ID (sessionStorage) */
21
+ current_tab: "lv_insights_ct",
22
+ /** Key for all tabs registry */
23
+ all_tabs: "lv_insights_at",
24
+ /** Device JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
25
+ device_token: "lv_aud_device",
26
+ /** Session JWT for direct mode (1yr expiry, rotated on /welcome, analytics-only scope) */
27
+ session_token: "lv_aud_session",
28
+ /** Cached insights mode ('proxy' | 'direct') */
29
+ mode: "lv_aud_mode",
30
+ /** Key to store session data **/
31
+ session: "lv_insights_session"
32
+ }, ke = () => {
33
+ if (typeof window > "u" || !("localStorage" in window))
34
+ return !1;
35
+ try {
36
+ const e = "__levo_test__";
37
+ return window.localStorage.setItem(e, "test"), window.localStorage.removeItem(e), !0;
38
+ } catch {
39
+ return !1;
40
+ }
41
+ }, G = {
42
+ isIdentified: !1,
43
+ isIdentifying: !1,
44
+ sessionId: null,
45
+ deviceId: null,
46
+ deviceToken: null,
47
+ sessionToken: null,
48
+ allTabs: [],
49
+ mode: "proxy",
50
+ insightsBaseUrl: null,
51
+ identity: null
52
+ }, Ce = JSON.stringify, ie = (e) => {
53
+ if (!e) return G;
54
+ try {
55
+ return JSON.parse(e);
56
+ } catch {
57
+ return G;
58
+ }
59
+ }, b = E(G), x = b.set;
60
+ let j = !1;
61
+ const Q = [], U = () => {
62
+ j || (j = !0, Q.forEach((e) => {
63
+ e();
64
+ }), Q.length = 0);
65
+ }, Dt = (e) => {
66
+ j ? e() : Q.push(e);
67
+ };
68
+ if (ke()) {
69
+ const e = localStorage.getItem(_.session);
70
+ e && x(ie(e)), U(), b.set = (t) => {
71
+ x(t);
72
+ try {
73
+ localStorage.setItem(_.session, Ce(t));
74
+ } catch {
75
+ }
76
+ }, window.addEventListener("storage", (t) => {
77
+ t.key === _.session && x(ie(t.newValue));
78
+ });
79
+ } else if (typeof BroadcastChannel < "u") {
80
+ const e = new BroadcastChannel(_.session);
81
+ e.onmessage = (t) => {
82
+ const { type: n, value: s } = t.data;
83
+ n === "UPDATE" && s ? x(s) : n === "QUERY" ? j && e.postMessage({ type: "RESPONSE", value: b.get() }) : n === "RESPONSE" && s && (x(s), U());
84
+ }, b.set = (t) => {
85
+ x(t), e.postMessage({ type: "UPDATE", value: t });
86
+ }, e.postMessage({ type: "QUERY" }), setTimeout(() => {
87
+ U();
88
+ }, 150);
89
+ } else
90
+ U();
91
+ const ee = () => b.get(), re = (e) => {
92
+ b.set({ ...ee(), ...e });
93
+ }, Mt = de(
94
+ b,
95
+ (e) => e.insightsBaseUrl !== null && e.identity !== null
96
+ ), Re = 10, Ne = 2e3, oe = 500, w = E([]), F = E(0), Le = de(w, (e) => e.length ?? 0), A = E(null), Pt = () => {
97
+ let e = !1;
98
+ return b.subscribe((t) => {
99
+ if (t.isIdentified && !e) {
100
+ e = !0;
101
+ const n = w.get();
102
+ n.length > 0 && $(n);
103
+ }
104
+ });
105
+ }, B = () => w.get(), Ie = () => Le.get(), $ = (e) => {
106
+ const { workspace: t, debug: n, site_id: s, page_id: r } = Z(), { isIdentified: a, mode: c, sessionId: l, deviceId: o, sessionToken: i, deviceToken: f, insightsBaseUrl: d } = ee();
107
+ if (e.length === 0 || !a || !d || !t)
108
+ return;
109
+ const p = e.map(
110
+ (m) => ({
111
+ // Default values from stores
112
+ workspace_id: t,
113
+ site_id: s ?? void 0,
114
+ session_id: l ?? void 0,
115
+ device_id: o ?? void 0,
116
+ identifier: r ?? void 0,
117
+ hostname: window.location.hostname,
118
+ pathname: window.location.pathname,
119
+ page_title: document.title,
120
+ url: window.location.href,
121
+ tab_id: "",
122
+ tab_count: 0,
123
+ // Event values override defaults (includes tab_id, tab_count captured at track time)
124
+ ...m,
125
+ // Ensure required fields have values
126
+ event: m.event,
127
+ created_at: m.created_at,
128
+ resource: m.resource ?? "page",
129
+ properties: m.properties ?? {}
130
+ })
131
+ );
132
+ if (w.set([]), n) {
133
+ console.log("[@levo-so/insights] Debug mode enabled. Events batch:", p);
134
+ return;
135
+ }
136
+ const y = `${d}/v1/insights/event/bulk?workspace=${t}`, C = {
137
+ "Content-Type": "application/json",
138
+ ..._e({ deviceToken: f, sessionToken: i, mode: c })
139
+ };
140
+ c === "proxy" && navigator.sendBeacon && navigator.sendBeacon(y, JSON.stringify(p)) || fetch(y, {
141
+ method: "POST",
142
+ body: JSON.stringify(p),
143
+ headers: C,
144
+ keepalive: !0,
145
+ credentials: c === "proxy" ? "include" : "omit"
146
+ }).catch(() => {
147
+ });
148
+ }, Oe = () => {
149
+ if (A.get()) return;
150
+ const e = setTimeout(() => {
151
+ $(B()), A.set(null);
152
+ }, Ne);
153
+ A.set(e);
154
+ }, fe = () => {
155
+ const e = A.get();
156
+ e && (clearTimeout(e), A.set(null));
157
+ }, Ut = (e) => {
158
+ const { debug: t } = Z(), n = F.get();
159
+ if (n >= oe) {
160
+ t && console.warn(`[@levo-so/core] Event limit (${oe}) reached for this page`);
161
+ return;
162
+ }
163
+ F.set(n + 1);
164
+ const s = w.get();
165
+ w.set([...s, e]);
166
+ const { isIdentified: r } = ee();
167
+ Ie() >= Re ? (fe(), $(B())) : r && Oe();
168
+ }, jt = () => F.set(0), Ft = () => {
169
+ w.set([]), F.set(0), fe();
170
+ }, O = X({
171
+ status: "active",
172
+ seconds: 0
173
+ }), Bt = (e) => {
174
+ if (typeof window > "u") return () => {
175
+ };
176
+ const s = xe({
177
+ timeout: 6e4,
178
+ throttle: 1e3,
179
+ onIdle: (a) => {
180
+ O.set({ status: "idle", seconds: a });
181
+ },
182
+ onWakeUp: (a) => {
183
+ O.set({ status: "active", seconds: a });
184
+ }
185
+ }), r = O.listen((a) => {
186
+ a.seconds > 0 && (a.status === "idle" ? e.track("user.idle", {
187
+ seconds_active: a.seconds
188
+ }) : e.track("user.active", {
189
+ seconds_idle: a.seconds
190
+ }));
191
+ });
192
+ return () => {
193
+ r(), s.disable(), O.set({ status: "active", seconds: 0 });
194
+ };
195
+ }, Ae = () => O.get();
196
+ class We extends Error {
197
+ }
198
+ class v extends Error {
199
+ code;
200
+ title;
201
+ status;
202
+ type;
203
+ errors;
204
+ constructor(t) {
205
+ super(t.description), this.name = "Levo Request Error", this.status = t.status, this.code = t.code, this.title = t.title, this.type = t.type, this.errors = t.errors;
206
+ }
207
+ /**
208
+ * Get validation errors for form fields
209
+ */
210
+ get fieldErrors() {
211
+ return this.errors || [];
212
+ }
213
+ /**
214
+ * Check if this is a validation error with field-specific errors
215
+ */
216
+ get hasFieldErrors() {
217
+ return !!this.errors?.length;
218
+ }
219
+ }
220
+ const $e = (e) => e instanceof We || e instanceof Error && "response" in e && "status" in e && "url" in e, ae = (e) => {
221
+ if (e instanceof v)
222
+ return e;
223
+ if ($e(e)) {
224
+ let t = e?.json;
225
+ if (!t && (e?.text || e?.message))
226
+ try {
227
+ t = JSON.parse(e.text || e.message);
228
+ } catch {
229
+ }
230
+ if (t) {
231
+ const n = t;
232
+ return new v({
233
+ status: n?.content?.status || e?.status || 500,
234
+ code: n?.content?.code || "Unknown",
235
+ title: n?.content?.title || `HTTP ${e?.status || 500} Error`,
236
+ description: n?.content?.description || n?.content?.errors?.[0]?.message || `Request failed with status ${e?.status || 500}`,
237
+ type: n?.content?.type,
238
+ errors: n?.content?.errors
239
+ });
240
+ }
241
+ return new v({
242
+ status: e?.status || 500,
243
+ code: "HTTP_ERROR",
244
+ title: `HTTP ${e?.status || 500} Error`,
245
+ description: `Request failed with status ${e?.status || 500}`
246
+ });
247
+ }
248
+ if (e instanceof TypeError) {
249
+ if (e?.message.includes("Failed to fetch") || e?.message.includes("Network request failed") || e?.message.includes("fetch"))
250
+ return new v({
251
+ status: 0,
252
+ code: "NETWORK_ERROR",
253
+ title: "Network Error",
254
+ description: "Unable to connect to the server. Please check your internet connection."
255
+ });
256
+ if (e?.message.includes("CORS") || e?.message.includes("cross-origin"))
257
+ return new v({
258
+ status: 0,
259
+ code: "CORS_ERROR",
260
+ title: "CORS Error",
261
+ description: "Cross-origin request blocked. Please contact support."
262
+ });
263
+ }
264
+ return e?.name === "AbortError" || e instanceof DOMException ? new v({
265
+ status: 408,
266
+ code: "REQUEST_TIMEOUT",
267
+ title: "Request Timeout",
268
+ description: "The request was cancelled or timed out. Please try again."
269
+ }) : e?.request ? new v({
270
+ status: e?.response?.status || 500,
271
+ code: e?.code || "REQUEST_ERROR",
272
+ title: "Request Error",
273
+ description: e?.message || "An error occurred while making the request"
274
+ }) : new v({
275
+ status: 500,
276
+ code: "UNKNOWN_ERROR",
277
+ title: "Unexpected Error",
278
+ description: e?.message || "Something unexpected happened"
279
+ });
280
+ }, ge = [
281
+ "TextWidget",
282
+ "CurrencyWidget",
283
+ "TextareaWidget",
284
+ "GeocoderWidget",
285
+ "MultiGeocoderWidget",
286
+ "DropdownWidget",
287
+ "ToggleCheckboxWidget",
288
+ "RadioWidget",
289
+ "NumberWidget",
290
+ "EmailWidget",
291
+ "PhoneWidget",
292
+ "URLWidget",
293
+ "DateWidget",
294
+ "TimeWidget",
295
+ "SwitchWidget",
296
+ "RichTextWidget",
297
+ "DateTimeWidget",
298
+ "CheckboxWidget",
299
+ "ImageUploadWidget",
300
+ "MultiImageUploadWidget",
301
+ "FileUploadWidget",
302
+ "MultiFileUploadWidget",
303
+ "MultiDropdownWidget",
304
+ "MultiTextWidget"
305
+ ], De = [
306
+ "CollectionWidget",
307
+ "ArrayWidget",
308
+ "RecordWidget",
309
+ "JSONWidget",
310
+ "SlugWidget"
311
+ ], Me = [
312
+ ...ge,
313
+ ...De
314
+ ];
315
+ ge.reduce(
316
+ (e, t) => (e[t] = t, e),
317
+ {}
318
+ );
319
+ Me.reduce(
320
+ (e, t) => (e[t] = t, e),
321
+ {}
322
+ );
323
+ const Pe = ["image", "video", "audio", "document"];
324
+ Pe.reduce(
325
+ (e, t) => (e[t] = t, e),
326
+ {}
327
+ );
328
+ const Ue = (e) => e.reduce((t, n) => (t[n] = n, t), {}), je = [
329
+ // Bevy Events
330
+ "bevy.collection.filled",
331
+ "bevy.collection.submitted",
332
+ "bevy.collection.view",
333
+ // Block Events
334
+ "block.view",
335
+ // Blog Events
336
+ "blog.post.view",
337
+ // Event Events
338
+ "event.booking.confirmed",
339
+ "event.booking.initiated",
340
+ "event.booking.pending",
341
+ "event.coupon.applied",
342
+ "event.event.view",
343
+ // Form Events
344
+ "form.change",
345
+ "form.submit",
346
+ // Membership Events
347
+ "membership.account.signin",
348
+ "membership.account.signout",
349
+ "membership.account.signup",
350
+ // UI Events
351
+ "button.click",
352
+ "page.bounce",
353
+ "page.click",
354
+ "page.copy",
355
+ "page.impression",
356
+ "page.scroll",
357
+ "page.view",
358
+ "page.selection",
359
+ // User Activity Events
360
+ "user.active",
361
+ "user.idle"
362
+ ], Ht = Ue(je), L = E(
363
+ "active"
364
+ /* ACTIVE */
365
+ ), Fe = () => typeof document > "u" ? "active" : document.visibilityState === "hidden" ? "hidden" : document.hasFocus() ? "active" : "passive", qt = (e) => {
366
+ if (typeof window > "u") return () => {
367
+ };
368
+ let t = !1;
369
+ const n = (i) => {
370
+ if (t) return;
371
+ t = !0;
372
+ const f = Ae(), d = {};
373
+ f.seconds > 0 && (f.status === "idle" ? d.seconds_idle = f.seconds : d.seconds_active = f.seconds);
374
+ try {
375
+ e.track("page.bounce", {
376
+ resource: "page",
377
+ ...d,
378
+ ...i
379
+ }), $(B());
380
+ } catch (p) {
381
+ console.error("[insights] Failed to send bounce event", ae(p));
382
+ }
383
+ }, s = () => {
384
+ const i = performance.getEntriesByType("navigation")?.[0];
385
+ let f = i?.type === "navigate";
386
+ if (!f)
387
+ try {
388
+ const d = document.activeElement;
389
+ d?.tagName === "A" && d.href && new URL(d.href).origin !== window.location.origin && (f = !0);
390
+ } catch (d) {
391
+ console.warn("[insights] Failed to parse link destination", ae(d));
392
+ }
393
+ n({
394
+ is_navigating_away: f,
395
+ navigation_type: i?.type,
396
+ trigger: "beforeunload"
397
+ });
398
+ }, r = (i) => {
399
+ switch (i.type) {
400
+ case "pageshow":
401
+ case "resume":
402
+ case "blur":
403
+ case "focus":
404
+ case "visibilitychange":
405
+ L.set(Fe());
406
+ break;
407
+ case "freeze":
408
+ L.set(
409
+ "frozen"
410
+ /* FROZEN */
411
+ );
412
+ break;
413
+ case "pagehide":
414
+ L.set(
415
+ i.persisted ? "frozen" : "terminated"
416
+ /* TERMINATED */
417
+ );
418
+ break;
419
+ }
420
+ }, a = ["pageshow", "pagehide", "focus", "blur", "visibilitychange", "resume", "freeze"];
421
+ a.forEach((i) => {
422
+ window.addEventListener(i, r, { capture: !0 });
423
+ }), window.addEventListener("beforeunload", s);
424
+ const c = L.listen((i) => {
425
+ i === "frozen" || i === "terminated" ? n({
426
+ state: i,
427
+ trigger: "lifecycle"
428
+ }) : i === "hidden" && $(B());
429
+ });
430
+ let l = W.get().page_id;
431
+ const o = W.listen((i) => {
432
+ i.page_id !== l && (t = !1, l = i.page_id);
433
+ });
434
+ return () => {
435
+ a.forEach((i) => {
436
+ window.removeEventListener(i, r, { capture: !0 });
437
+ }), window.removeEventListener("beforeunload", s), c(), o(), t = !1, L.set(
438
+ "active"
439
+ /* ACTIVE */
440
+ );
441
+ };
442
+ }, H = (e) => Object.prototype.toString.call(e) == "[object String]", Be = (e, t) => e.indexOf(t) !== -1, k = (e) => e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""), pe = (e) => e === void 0, He = (e) => e === null, me = (e) => pe(e) || He(e), he = (e) => !!e && e?.nodeType === 3;
443
+ function qe(e) {
444
+ return !!e && e?.nodeType === 1;
445
+ }
446
+ function Ve(e, t) {
447
+ return !!e && !!e?.tagName && e?.tagName.toLowerCase() === t.toLowerCase();
448
+ }
449
+ function Ye(e) {
450
+ return e ? k(e).split(/\s+/) : [];
451
+ }
452
+ function ze(e) {
453
+ let t = "";
454
+ switch (typeof e?.className) {
455
+ case "string":
456
+ t = e?.className;
457
+ break;
458
+ // TODO: when is this ever used?
459
+ case "object":
460
+ t = (e?.className && "baseVal" in e.className ? (e?.className).baseVal : null) || e?.getAttribute("class") || "";
461
+ break;
462
+ default:
463
+ t = "";
464
+ }
465
+ return Ye(t);
466
+ }
467
+ const g = (e, t = 255) => me(e) ? "" : k(e).split(/(\s+)/).filter((n) => ne(n)).join("").replace(/[\r\n]/g, " ").replace(/[ ]+/g, " ").substring(0, t), be = ["span", "strong", "em", "i", "b", "mark", "code", "small", "sub", "sup", "label"], te = (e) => {
468
+ let t = "";
469
+ if (Je(e) && e?.childNodes && e?.childNodes.length) {
470
+ for (const n of e.childNodes)
471
+ he(n) && n.textContent && (t += g(n.textContent) ?? "");
472
+ if (!k(t)) {
473
+ const n = e.querySelectorAll(be.join(", "));
474
+ for (const s of n) {
475
+ const r = s.textContent;
476
+ r && (t += `${g(r)} `);
477
+ }
478
+ }
479
+ if (!k(t) && e instanceof HTMLElement) {
480
+ const n = e.innerText;
481
+ n && (t = g(n.substring(0, 500)));
482
+ }
483
+ }
484
+ return k(t);
485
+ }, Ge = (e) => pe(e.target) ? e?.srcElement || null : e?.target?.shadowRoot ? e?.composedPath()?.[0] || null : e?.target || null, Qe = (e, t) => {
486
+ if (!window || !e || Ve(e, "html") || !qe(e))
487
+ return !1;
488
+ const n = window.getComputedStyle(e);
489
+ if (n && n.getPropertyValue("cursor") === "pointer" && t.type === "click")
490
+ return !0;
491
+ switch (e?.tagName.toLowerCase()) {
492
+ case "html":
493
+ return !1;
494
+ case "form":
495
+ return t.type === "submit";
496
+ case "input":
497
+ case "select":
498
+ case "textarea":
499
+ return ["change", "click"].includes(t.type);
500
+ default:
501
+ return t.type === "click";
502
+ }
503
+ }, Ke = /* @__PURE__ */ new Set([
504
+ "password",
505
+ "passwd",
506
+ "pwd",
507
+ "creditcard",
508
+ "cardnumber",
509
+ "ccnum",
510
+ "ccnumber",
511
+ "cvv",
512
+ "cvc",
513
+ "csc",
514
+ "securitycode",
515
+ "ssn",
516
+ "socialsecurity",
517
+ "routingnumber",
518
+ "accountnumber",
519
+ "bankaccount",
520
+ "secretkey",
521
+ "apikey",
522
+ "accesstoken"
523
+ ]);
524
+ function Je(e) {
525
+ if (Be(ze(e), "ph-include"))
526
+ return !0;
527
+ const t = e.type || "";
528
+ if (H(t))
529
+ switch (t.toLowerCase()) {
530
+ case "hidden":
531
+ return !1;
532
+ case "password":
533
+ return !1;
534
+ }
535
+ const n = e.name || e?.id || "";
536
+ if (H(n)) {
537
+ const s = n.toLowerCase().replace(/[^a-z]/g, "");
538
+ if (Ke.has(s))
539
+ return !1;
540
+ }
541
+ return !0;
542
+ }
543
+ const ye = "(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11})", Xe = new RegExp(`^(?:${ye})$`), Ze = new RegExp(ye), ve = "\\d{3}-?\\d{2}-?\\d{4}", et = new RegExp(`^(${ve})$`), tt = new RegExp(`(${ve})`), ne = (e, t = !0) => !(me(e) || H(e) && (e = k(e), (t ? Xe : Ze).test((e || "").replace(/[- ]/g, "")) || (t ? et : tt).test(e))), nt = (e) => H(e) ? e.substring(0, 10) === "_ngcontent" || e.substring(0, 7) === "_nghost" : !1, st = (e) => {
544
+ let t = te(e);
545
+ return t = `${t} ${Te(e)}`.trim(), ne(t) ? t : "";
546
+ };
547
+ function Te(e) {
548
+ let t = "";
549
+ if (e?.childNodes.length)
550
+ for (const n of e.childNodes) {
551
+ const s = n.tagName?.toLowerCase();
552
+ if (n && s && be.includes(s))
553
+ try {
554
+ const r = te(n);
555
+ t = `${t} ${r}`.trim(), n?.childNodes.length && (t = `${t} ${Te(n)}`.trim());
556
+ } catch {
557
+ }
558
+ }
559
+ return t;
560
+ }
561
+ const it = (e) => {
562
+ const t = e.tagName?.toLowerCase(), n = t === "a" || t === "button" ? st(e) : te(e);
563
+ if (n) return { text: n, source: "text" };
564
+ const s = e.getAttribute("aria-label");
565
+ if (s) return { text: g(s), source: "aria-label" };
566
+ const r = e.getAttribute("title");
567
+ if (r) return { text: g(r), source: "title" };
568
+ const a = e.getAttribute("data-track-label");
569
+ if (a) return { text: g(a), source: "data-track-label" };
570
+ const c = e.querySelector("img[alt], svg[aria-label]");
571
+ if (c) {
572
+ const o = c.getAttribute("alt") || c.getAttribute("aria-label");
573
+ if (o) return { text: g(o), source: "alt" };
574
+ }
575
+ const l = e.getAttribute("placeholder");
576
+ if (l) return { text: g(l), source: "placeholder" };
577
+ if (e instanceof HTMLElement && e.innerText) {
578
+ const o = e.innerText.substring(0, 500);
579
+ if (o.trim())
580
+ return { text: g(o), source: "innerText" };
581
+ }
582
+ return { text: "", source: "none" };
583
+ }, rt = ["input", "textarea", "select"], ot = (e) => {
584
+ const t = e?.tagName?.toLowerCase(), n = {
585
+ element: t
586
+ }, s = it(e);
587
+ n.text = s.text, n.text_source = s.source;
588
+ const r = e.getAttribute("aria-label");
589
+ r && (n.aria_label = g(r));
590
+ const a = e.getAttribute("role");
591
+ a && (n.role = a);
592
+ const c = {};
593
+ for (const o of e.attributes)
594
+ (o.name.startsWith("data-track-") || o.name.startsWith("data-analytics-")) && (c[o.name] = g(o.value));
595
+ Object.keys(c).length && (n.tracking_data = c);
596
+ const l = Array.from(e.attributes).reduce(
597
+ (o, i) => {
598
+ if (ne(i.value) && !nt(i.name)) {
599
+ if (i.name === "class" || i.name.startsWith("data-track-") || i.name.startsWith("data-analytics-"))
600
+ return o;
601
+ o[i.name] = typeof i?.value == "string" ? g(i.value) : i.value;
602
+ }
603
+ return o;
604
+ },
605
+ {}
606
+ );
607
+ if (n.attributes = l, rt.includes(t) || e?.getAttribute("contenteditable") === "true") {
608
+ let o;
609
+ e.matches('input[type="checkbox"], input[type="radio"]') ? o = e.checked : e.matches("input, select, textarea") && !e.matches('input[type="password"]') && (o = e.value), o !== void 0 && (n.value = typeof o == "string" || o === null ? g(o, 1024) : o);
610
+ let i = "";
611
+ n?.attributes.id && (i = g(
612
+ document.querySelector(`label[for="${n?.attributes.id}"]`)?.textContent?.trim() || ""
613
+ ));
614
+ const f = e.closest("label");
615
+ i || (i = g(f?.textContent?.trim() || "")), i && (n.label = i);
616
+ }
617
+ return n;
618
+ }, Vt = (e, t) => {
619
+ let n = Ge(e);
620
+ he(n) && (n = n.parentNode || null);
621
+ const s = ["copy", "cut"].includes(t);
622
+ if (n && (s || Qe(n, e))) {
623
+ const r = ot(n);
624
+ if (s) {
625
+ const a = g(window?.getSelection()?.toString()), c = e?.type || "clipboard";
626
+ r.copy_text = a ?? "", r.copy_type = c;
627
+ }
628
+ return r;
629
+ }
630
+ return null;
631
+ }, K = E(null), Yt = (e) => {
632
+ if (typeof window > "u") return () => {
633
+ };
634
+ let t = sessionStorage.getItem(_.current_tab);
635
+ const { allTabs: n } = b.get();
636
+ t && n.includes(t) && (t = null), t || (t = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`, sessionStorage.setItem(_.current_tab, t));
637
+ const s = t;
638
+ K.set(s), n.includes(s) || re({ allTabs: [...n, s] });
639
+ const r = () => {
640
+ if (!s) return;
641
+ const { allTabs: a } = b.get();
642
+ if (a.includes(s)) {
643
+ const c = a.filter((l) => l !== s);
644
+ re({ allTabs: c });
645
+ }
646
+ };
647
+ return window.addEventListener("beforeunload", r), () => {
648
+ window.removeEventListener("beforeunload", r), r(), K.set(null);
649
+ };
650
+ }, zt = () => K.get();
651
+ function J(e) {
652
+ var t = typeof e;
653
+ return e != null && (t == "object" || t == "function");
654
+ }
655
+ var at = typeof global == "object" && global && global.Object === Object && global, ct = typeof self == "object" && self && self.Object === Object && self, we = at || ct || Function("return this")(), V = function() {
656
+ return we.Date.now();
657
+ }, lt = /\s/;
658
+ function ut(e) {
659
+ for (var t = e.length; t-- && lt.test(e.charAt(t)); )
660
+ ;
661
+ return t;
662
+ }
663
+ var dt = /^\s+/;
664
+ function ft(e) {
665
+ return e && e.slice(0, ut(e) + 1).replace(dt, "");
666
+ }
667
+ var q = we.Symbol, Ee = Object.prototype, gt = Ee.hasOwnProperty, pt = Ee.toString, I = q ? q.toStringTag : void 0;
668
+ function mt(e) {
669
+ var t = gt.call(e, I), n = e[I];
670
+ try {
671
+ e[I] = void 0;
672
+ var s = !0;
673
+ } catch {
674
+ }
675
+ var r = pt.call(e);
676
+ return s && (t ? e[I] = n : delete e[I]), r;
677
+ }
678
+ var ht = Object.prototype, bt = ht.toString;
679
+ function yt(e) {
680
+ return bt.call(e);
681
+ }
682
+ var vt = "[object Null]", Tt = "[object Undefined]", ce = q ? q.toStringTag : void 0;
683
+ function wt(e) {
684
+ return e == null ? e === void 0 ? Tt : vt : ce && ce in Object(e) ? mt(e) : yt(e);
685
+ }
686
+ function Et(e) {
687
+ return e != null && typeof e == "object";
688
+ }
689
+ var St = "[object Symbol]";
690
+ function xt(e) {
691
+ return typeof e == "symbol" || Et(e) && wt(e) == St;
692
+ }
693
+ var le = NaN, _t = /^[-+]0x[0-9a-f]+$/i, kt = /^0b[01]+$/i, Ct = /^0o[0-7]+$/i, Rt = parseInt;
694
+ function ue(e) {
695
+ if (typeof e == "number")
696
+ return e;
697
+ if (xt(e))
698
+ return le;
699
+ if (J(e)) {
700
+ var t = typeof e.valueOf == "function" ? e.valueOf() : e;
701
+ e = J(t) ? t + "" : t;
702
+ }
703
+ if (typeof e != "string")
704
+ return e === 0 ? e : +e;
705
+ e = ft(e);
706
+ var n = kt.test(e);
707
+ return n || Ct.test(e) ? Rt(e.slice(2), n ? 2 : 8) : _t.test(e) ? le : +e;
708
+ }
709
+ var Nt = "Expected a function", Lt = Math.max, It = Math.min;
710
+ function Se(e, t, n) {
711
+ var s, r, a, c, l, o, i = 0, f = !1, d = !1, p = !0;
712
+ if (typeof e != "function")
713
+ throw new TypeError(Nt);
714
+ t = ue(t) || 0, J(n) && (f = !!n.leading, d = "maxWait" in n, a = d ? Lt(ue(n.maxWait) || 0, t) : a, p = "trailing" in n ? !!n.trailing : p);
715
+ function y(u) {
716
+ var h = s, T = r;
717
+ return s = r = void 0, i = u, c = e.apply(T, h), c;
718
+ }
719
+ function C(u) {
720
+ return i = u, l = setTimeout(S, t), f ? y(u) : c;
721
+ }
722
+ function m(u) {
723
+ var h = u - o, T = u - i, se = t - h;
724
+ return d ? It(se, a - T) : se;
725
+ }
726
+ function R(u) {
727
+ var h = u - o, T = u - i;
728
+ return o === void 0 || h >= t || h < 0 || d && T >= a;
729
+ }
730
+ function S() {
731
+ var u = V();
732
+ if (R(u))
733
+ return D(u);
734
+ l = setTimeout(S, m(u));
735
+ }
736
+ function D(u) {
737
+ return l = void 0, p && s ? y(u) : (s = r = void 0, c);
738
+ }
739
+ function M() {
740
+ l !== void 0 && clearTimeout(l), i = 0, s = o = r = l = void 0;
741
+ }
742
+ function P() {
743
+ return l === void 0 ? c : D(V());
744
+ }
745
+ function N() {
746
+ var u = V(), h = R(u);
747
+ if (s = arguments, r = this, o = u, h) {
748
+ if (l === void 0)
749
+ return C(o);
750
+ if (d)
751
+ return clearTimeout(l), l = setTimeout(S, t), y(o);
752
+ }
753
+ return l === void 0 && (l = setTimeout(S, t)), c;
754
+ }
755
+ return N.cancel = M, N.flush = P, N;
756
+ }
757
+ const Y = X({
758
+ depth: 0,
759
+ speedCategory: "read",
760
+ direction: "down"
761
+ }), Gt = (e) => {
762
+ if (typeof window > "u") return () => {
763
+ };
764
+ let t = {
765
+ prevMilestone: -1,
766
+ // Use -1 to ensure first milestone (even 0) is tracked
767
+ prevScrollY: 0,
768
+ prevTime: Date.now()
769
+ };
770
+ const n = 5, s = 300, r = 250, a = () => {
771
+ const i = window.scrollY, f = document.documentElement.scrollHeight, d = window.innerHeight, p = f - d;
772
+ if (p <= 0) return;
773
+ const y = Math.round(i / p * 100), C = Math.max(0, Math.min(100, y)), m = Math.floor(C / n) * n, { prevMilestone: R, prevScrollY: S, prevTime: D } = t;
774
+ if (m === R) return;
775
+ const M = Date.now(), P = (M - D) / 1e3, N = Math.abs(i - S), u = P > 0 ? N / P : 0, h = m > R ? "down" : "up", T = u > s ? "scan" : "read";
776
+ Y.set({
777
+ depth: m,
778
+ speedCategory: T,
779
+ direction: h
780
+ }), t = {
781
+ prevMilestone: m,
782
+ prevScrollY: i,
783
+ prevTime: M
784
+ };
785
+ }, c = Se(a, r);
786
+ window.addEventListener("scroll", c);
787
+ let l = 0;
788
+ const o = Y.listen((i) => {
789
+ i.depth !== l && (l = i.depth, e.track("page.scroll", {
790
+ depth: i.depth,
791
+ speed_category: i.speedCategory,
792
+ direction: i.direction
793
+ }));
794
+ });
795
+ return a(), () => {
796
+ window.removeEventListener("scroll", c), c.cancel(), o(), Y.set({
797
+ depth: 0,
798
+ speedCategory: "read",
799
+ direction: "down"
800
+ });
801
+ };
802
+ }, z = E(null), Qt = (e) => {
803
+ if (typeof window > "u") return () => {
804
+ };
805
+ const n = Se(() => {
806
+ const r = window.getSelection();
807
+ if (r && r.rangeCount > 0) {
808
+ const a = r.toString().trim();
809
+ a && z.set(a);
810
+ }
811
+ }, 1e3);
812
+ document.addEventListener("selectionchange", n);
813
+ const s = z.listen((r) => {
814
+ r && e.track("page.selection", {
815
+ text: g(r)
816
+ });
817
+ });
818
+ return () => {
819
+ document.removeEventListener("selectionchange", n), n.cancel(), s(), z.set(null);
820
+ };
821
+ };
822
+ export {
823
+ W as $,
824
+ Pt as A,
825
+ Bt as B,
826
+ qt as C,
827
+ Yt as D,
828
+ Gt as E,
829
+ Qt as F,
830
+ Ht as G,
831
+ w as a,
832
+ F as b,
833
+ Le as c,
834
+ Mt as d,
835
+ b as e,
836
+ O as f,
837
+ L as g,
838
+ K as h,
839
+ Y as i,
840
+ z as j,
841
+ ot as k,
842
+ Vt as l,
843
+ Z as m,
844
+ ee as n,
845
+ zt as o,
846
+ ae as p,
847
+ _e as q,
848
+ jt as r,
849
+ Wt as s,
850
+ Ut as t,
851
+ re as u,
852
+ $t as v,
853
+ Dt as w,
854
+ $ as x,
855
+ B as y,
856
+ Ft as z
857
+ };