solo-analytics 0.2.0 → 0.3.2

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.
@@ -1,475 +0,0 @@
1
- function k(e, t = {}) {
2
- const i = t.vendor ?? (typeof navigator < "u" ? navigator.vendor : ""), n = t.innerWidth ?? (typeof window < "u" ? window.innerWidth : 1024), r = t.innerHeight ?? (typeof window < "u" ? window.innerHeight : 768), f = t.maxTouchPoints ?? (typeof navigator < "u" && "maxTouchPoints" in navigator ? navigator.maxTouchPoints : 0), o = () => {
3
- const s = [
4
- { name: "Edge", regex: /Edg(?:e|A|iOS)?\/([0-9\.]+)/ },
5
- { name: "Samsung Browser", regex: /SamsungBrowser\/([0-9\.]+)/ },
6
- { name: "Opera", regex: /(?:Opera|OPR)\/([0-9\.]+)/ },
7
- { name: "Firefox", regex: /Firefox\/([0-9\.]+)/ },
8
- { name: "Chrome", regex: /Chrome\/([0-9\.]+)/ },
9
- { name: "Safari", regex: /Version\/([0-9\.]+).*Safari/ },
10
- { name: "IE", regex: /MSIE|Trident/ }
11
- ];
12
- for (const l of s) {
13
- const a = e.match(l.regex);
14
- if (a) {
15
- const c = a[1] || "", p = c.split(".")[0] || "";
16
- let v = "Unknown", h = "";
17
- if (e.includes("AppleWebKit")) {
18
- const g = e.match(/AppleWebKit\/([0-9\.]+)/);
19
- v = "WebKit", h = g ? g[1] : "";
20
- } else if (e.includes("Gecko")) {
21
- v = "Gecko";
22
- const g = e.match(/rv:([0-9\.]+)/);
23
- h = g ? g[1] : "";
24
- } else if (e.includes("Trident")) {
25
- v = "Trident";
26
- const g = e.match(/Trident\/([0-9\.]+)/);
27
- h = g ? g[1] : "";
28
- }
29
- return {
30
- name: l.name,
31
- version: c,
32
- major: p,
33
- userAgent: e,
34
- vendor: i,
35
- engine: v,
36
- engineVersion: h
37
- };
38
- }
39
- }
40
- return {
41
- name: "Unknown",
42
- version: "",
43
- major: "",
44
- userAgent: e,
45
- vendor: i,
46
- engine: "Unknown",
47
- engineVersion: ""
48
- };
49
- }, d = () => {
50
- const s = [
51
- { name: "iOS", regex: /iPhone|iPad|iPod/ },
52
- { name: "Android", regex: /Android ([0-9\.]+)/ },
53
- { name: "Windows", regex: /Windows NT ([0-9\.]+)/ },
54
- { name: "macOS", regex: /Mac OS X ([0-9_\.]+)/ },
55
- { name: "Linux", regex: /Linux/ }
56
- ];
57
- for (const l of s) {
58
- const a = e.match(l.regex);
59
- if (a) {
60
- let c = "";
61
- return a[1] && (c = l.name === "macOS" ? a[1].replace(/_/g, ".") : a[1]), {
62
- name: l.name,
63
- version: c,
64
- architecture: e.includes("x64") || e.includes("x86_64") ? "64-bit" : "32-bit"
65
- };
66
- }
67
- }
68
- return {
69
- name: "Unknown",
70
- version: "",
71
- architecture: e.includes("x64") || e.includes("x86_64") ? "64-bit" : "32-bit"
72
- };
73
- }, u = () => {
74
- const s = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e), l = /iPad|Android(?!.*Mobile)/i.test(e);
75
- let a = "Unknown", c = "Unknown";
76
- if (e.includes("iPhone") || e.includes("iPad") || e.includes("iPod"))
77
- a = "Apple", e.includes("iPhone") && (c = "iPhone"), e.includes("iPad") && (c = "iPad"), e.includes("iPod") && (c = "iPod");
78
- else if (e.includes("Samsung"))
79
- a = "Samsung";
80
- else if (e.includes("Pixel")) {
81
- a = "Google";
82
- const v = e.match(/Pixel ([0-9XL]+)/);
83
- v && (c = `Pixel ${v[1]}`);
84
- }
85
- const p = l ? "tablet" : s ? "mobile" : "desktop";
86
- return {
87
- type: p,
88
- vendor: a,
89
- model: c,
90
- orientation: r > n ? "portrait" : "landscape",
91
- isMobile: p === "mobile",
92
- isTablet: p === "tablet",
93
- isDesktop: p === "desktop",
94
- touch: f > 0
95
- };
96
- };
97
- return {
98
- browser: o(),
99
- os: d(),
100
- device: u()
101
- };
102
- }
103
- function T() {
104
- const e = () => !window.performance || !window.performance.navigation ? { type: "Unknown", redirectCount: 0 } : {
105
- type: ["navigate", "reload", "back_forward", "prerender"][window.performance.navigation.type] || "Unknown",
106
- redirectCount: window.performance.navigation.redirectCount
107
- }, t = () => {
108
- if (!window.performance || !window.performance.timing)
109
- return {
110
- loadTime: 0,
111
- domContentLoaded: 0,
112
- firstPaint: null,
113
- firstContentfulPaint: null
114
- };
115
- const n = window.performance.timing, r = n.loadEventEnd - n.navigationStart, f = n.domContentLoadedEventEnd - n.navigationStart;
116
- let o = null, d = null;
117
- if (window.performance && typeof window.performance.getEntriesByType == "function") {
118
- const u = window.performance.getEntriesByType("paint"), s = u.find((a) => a.name === "first-paint"), l = u.find((a) => a.name === "first-contentful-paint");
119
- s && (o = s.startTime), l && (d = l.startTime);
120
- }
121
- return {
122
- loadTime: r,
123
- domContentLoaded: f,
124
- firstPaint: o,
125
- firstContentfulPaint: d
126
- };
127
- };
128
- return {
129
- memory: (() => {
130
- if (window.performance && window.performance.memory) {
131
- const n = window.performance.memory;
132
- return {
133
- jsHeapSizeLimit: n.jsHeapSizeLimit,
134
- totalJSHeapSize: n.totalJSHeapSize,
135
- usedJSHeapSize: n.usedJSHeapSize
136
- };
137
- }
138
- return null;
139
- })(),
140
- navigation: e(),
141
- timing: t()
142
- };
143
- }
144
- function P() {
145
- const e = typeof navigator < "u" ? navigator.onLine : !1;
146
- let t = "unknown", i = 0, n = 0, r = !1;
147
- if (navigator && navigator.connection) {
148
- const f = navigator.connection;
149
- t = f.effectiveType || t, i = f.downlink || i, n = f.rtt || n, r = f.saveData || r;
150
- }
151
- return {
152
- online: e,
153
- effectiveType: t,
154
- downlink: i,
155
- rtt: n,
156
- saveData: r
157
- };
158
- }
159
- function S() {
160
- if (typeof window > "u" || typeof screen > "u")
161
- return {
162
- width: 0,
163
- height: 0,
164
- availWidth: 0,
165
- availHeight: 0,
166
- colorDepth: 0,
167
- orientation: "unknown",
168
- pixelRatio: 1,
169
- touchPoints: 0
170
- };
171
- let e = "unknown";
172
- window.innerHeight > window.innerWidth ? e = "portrait" : e = "landscape", screen.orientation && screen.orientation.type && (e = screen.orientation.type);
173
- const t = window.devicePixelRatio || 1, i = navigator.maxTouchPoints || 0;
174
- return {
175
- width: screen.width,
176
- height: screen.height,
177
- availWidth: screen.availWidth,
178
- availHeight: screen.availHeight,
179
- colorDepth: screen.colorDepth,
180
- orientation: e,
181
- pixelRatio: t,
182
- touchPoints: i
183
- };
184
- }
185
- function x() {
186
- if (typeof window > "u" || typeof navigator > "u")
187
- return {
188
- timeZone: "",
189
- language: "",
190
- languages: [],
191
- isRestricted: !1,
192
- doNotTrack: null,
193
- cookiesEnabled: !1,
194
- localStorage: !1,
195
- sessionStorage: !1
196
- };
197
- const e = Intl.DateTimeFormat().resolvedOptions().timeZone, t = navigator.language || "", i = navigator.languages ? Array.from(navigator.languages) : [t];
198
- let n = !1;
199
- try {
200
- n = window.self !== window.top;
201
- } catch {
202
- n = !0;
203
- }
204
- let r = null;
205
- navigator.doNotTrack === "1" || navigator.doNotTrack === "yes" ? r = !0 : (navigator.doNotTrack === "0" || navigator.doNotTrack === "no") && (r = !1);
206
- const f = navigator.cookieEnabled, o = (d) => {
207
- try {
208
- const u = window[d], s = `__test_${d}__`;
209
- return u.setItem(s, "test"), u.removeItem(s), !0;
210
- } catch {
211
- return !1;
212
- }
213
- };
214
- return {
215
- timeZone: e,
216
- language: t,
217
- languages: i,
218
- isRestricted: n,
219
- doNotTrack: r,
220
- cookiesEnabled: f,
221
- localStorage: o("localStorage"),
222
- sessionStorage: o("sessionStorage")
223
- };
224
- }
225
- function C(e, t = 2e3) {
226
- if (typeof window > "u") {
227
- Promise.resolve().then(e);
228
- return;
229
- }
230
- const i = () => {
231
- Promise.resolve(e());
232
- };
233
- if ("requestIdleCallback" in window) {
234
- window.requestIdleCallback(() => i(), { timeout: t });
235
- return;
236
- }
237
- setTimeout(i, 0);
238
- }
239
- async function D() {
240
- return new Promise((e) => {
241
- if (typeof window > "u") {
242
- e(!1);
243
- return;
244
- }
245
- const t = indexedDB.open("test");
246
- t.onerror = () => e(!0), t.onsuccess = () => e(!1), setTimeout(() => e(!1), 1e3);
247
- });
248
- }
249
- async function I() {
250
- if (typeof navigator > "u" || !navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices)
251
- return { hasCamera: null, hasMicrophone: null };
252
- try {
253
- const e = await navigator.mediaDevices.enumerateDevices(), t = e.some((n) => n.kind === "videoinput"), i = e.some((n) => n.kind === "audioinput");
254
- return { hasCamera: t, hasMicrophone: i };
255
- } catch {
256
- return { hasCamera: null, hasMicrophone: null };
257
- }
258
- }
259
- async function M() {
260
- if (typeof navigator > "u" || !navigator.getBattery)
261
- return { hasBattery: null, level: null, charging: null };
262
- try {
263
- const e = await navigator.getBattery();
264
- return {
265
- hasBattery: !0,
266
- level: e.level,
267
- charging: e.charging
268
- };
269
- } catch {
270
- return { hasBattery: null, level: null, charging: null };
271
- }
272
- }
273
- async function A() {
274
- if (typeof navigator > "u" || !navigator.permissions || !navigator.permissions.query)
275
- return {};
276
- const e = {}, t = [
277
- "geolocation",
278
- "notifications",
279
- "push",
280
- "midi",
281
- "camera",
282
- "microphone",
283
- "background-sync",
284
- "accelerometer",
285
- "gyroscope",
286
- "magnetometer"
287
- ], i = await Promise.all(
288
- t.map(async (n) => {
289
- try {
290
- const r = await navigator.permissions.query({ name: n });
291
- return [n, r.state];
292
- } catch {
293
- return [n, "not-supported"];
294
- }
295
- })
296
- );
297
- for (const [n, r] of i)
298
- e[n] = r;
299
- return e;
300
- }
301
- const B = () => ({
302
- browser: {
303
- name: "",
304
- version: "",
305
- major: "",
306
- userAgent: "",
307
- vendor: "",
308
- engine: "",
309
- engineVersion: ""
310
- },
311
- os: {
312
- name: "",
313
- version: "",
314
- architecture: ""
315
- },
316
- device: {
317
- type: "unknown",
318
- vendor: "",
319
- model: "",
320
- orientation: "portrait",
321
- isMobile: !1,
322
- isTablet: !1,
323
- isDesktop: !1,
324
- touch: !1
325
- },
326
- network: {
327
- online: !1,
328
- effectiveType: "",
329
- downlink: 0,
330
- rtt: 0,
331
- saveData: !1
332
- },
333
- screen: {
334
- width: 0,
335
- height: 0,
336
- availWidth: 0,
337
- availHeight: 0,
338
- colorDepth: 0,
339
- orientation: "",
340
- pixelRatio: 1,
341
- touchPoints: 0
342
- },
343
- performance: {
344
- memory: null,
345
- navigation: {
346
- type: "",
347
- redirectCount: 0
348
- },
349
- timing: {
350
- loadTime: 0,
351
- domContentLoaded: 0,
352
- firstPaint: null,
353
- firstContentfulPaint: null
354
- }
355
- },
356
- location: {
357
- timeZone: "",
358
- language: "",
359
- languages: [],
360
- isRestricted: !1,
361
- doNotTrack: null,
362
- cookiesEnabled: !1,
363
- localStorage: !1,
364
- sessionStorage: !1
365
- },
366
- pageVisibility: "visible",
367
- referrer: "",
368
- isIncognito: !1,
369
- hasCamera: null,
370
- hasMicrophone: null,
371
- hasBattery: null,
372
- batteryLevel: null,
373
- batteryCharging: null,
374
- permissions: {}
375
- });
376
- function E(e = {}) {
377
- const {
378
- autoRefresh: t = !1,
379
- refreshInterval: i = 3e4,
380
- trackVisibility: n = !0,
381
- detectFeatures: r = !0,
382
- lazyFeatures: f = !0
383
- } = e, o = B();
384
- let d = null, u = null, s = !1;
385
- const l = () => {
386
- if (typeof navigator > "u" || typeof window > "u")
387
- return;
388
- const m = navigator.userAgent, { browser: y, os: w, device: b } = k(m);
389
- Object.assign(o, {
390
- browser: y,
391
- os: w,
392
- device: b,
393
- screen: S(),
394
- location: x(),
395
- referrer: document.referrer
396
- });
397
- }, a = async () => {
398
- if (!r || s)
399
- return;
400
- const [m, y, w, b] = await Promise.all([
401
- D(),
402
- I(),
403
- M(),
404
- A()
405
- ]);
406
- s || Object.assign(o, {
407
- isIncognito: m,
408
- hasCamera: y.hasCamera,
409
- hasMicrophone: y.hasMicrophone,
410
- hasBattery: w.hasBattery,
411
- batteryLevel: w.level,
412
- batteryCharging: w.charging,
413
- permissions: b
414
- });
415
- }, c = () => {
416
- typeof navigator > "u" || typeof window > "u" || Object.assign(o, {
417
- network: P(),
418
- performance: T(),
419
- pageVisibility: document.visibilityState === "visible" ? "visible" : "hidden"
420
- });
421
- }, p = () => {
422
- if (!r)
423
- return;
424
- const m = () => {
425
- a();
426
- };
427
- if (f) {
428
- C(m);
429
- return;
430
- }
431
- m();
432
- };
433
- if (n && typeof document < "u") {
434
- const m = () => {
435
- o.pageVisibility = document.visibilityState === "visible" ? "visible" : "hidden";
436
- };
437
- document.addEventListener("visibilitychange", m), d = m;
438
- }
439
- return t && typeof window < "u" && (u = setInterval(c, i)), (() => {
440
- l(), c(), p();
441
- })(), {
442
- data: o,
443
- refresh: async () => {
444
- l(), c(), await a();
445
- },
446
- destroy: () => {
447
- s = !0, u !== null && (clearInterval(u), u = null), d && typeof document < "u" && (document.removeEventListener("visibilitychange", d), d = null);
448
- },
449
- get isMobile() {
450
- return o.device.isMobile;
451
- },
452
- get isTablet() {
453
- return o.device.isTablet;
454
- },
455
- get isDesktop() {
456
- return o.device.isDesktop;
457
- },
458
- get isOnline() {
459
- return o.network.online;
460
- },
461
- get isVisible() {
462
- return o.pageVisibility === "visible";
463
- },
464
- get browserName() {
465
- return o.browser.name;
466
- },
467
- get osName() {
468
- return o.os.name;
469
- }
470
- };
471
- }
472
- export {
473
- E as useSoloAnalytics
474
- };
475
- //# sourceMappingURL=solo-analytics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"solo-analytics.js","sources":["../src/utils/parseUserAgent.ts","../src/utils/performance.ts","../src/utils/network.ts","../src/utils/screen.ts","../src/utils/location.ts","../src/utils/scheduleIdle.ts","../src/utils/features.ts","../src/composables/useSoloAnalytics.ts"],"sourcesContent":["import { BrowserInfo, OSInfo, DeviceInfo } from '../types/analytics';\n\nexport interface ParseUserAgentOptions {\n vendor?: string;\n innerWidth?: number;\n innerHeight?: number;\n maxTouchPoints?: number;\n}\n\n/**\n * Parses the user agent string and returns detailed information about browser, OS, and device\n */\nexport function parseUserAgent(\n ua: string,\n options: ParseUserAgentOptions = {},\n): {\n browser: BrowserInfo;\n os: OSInfo;\n device: DeviceInfo;\n} {\n const vendor =\n options.vendor ??\n (typeof navigator !== 'undefined' ? navigator.vendor : '');\n const innerWidth =\n options.innerWidth ??\n (typeof window !== 'undefined' ? window.innerWidth : 1024);\n const innerHeight =\n options.innerHeight ??\n (typeof window !== 'undefined' ? window.innerHeight : 768);\n const maxTouchPoints =\n options.maxTouchPoints ??\n (typeof navigator !== 'undefined' && 'maxTouchPoints' in navigator\n ? navigator.maxTouchPoints\n : 0);\n\n // Browser detection\n const getBrowser = (): BrowserInfo => {\n const browsers = [\n { name: 'Edge', regex: /Edg(?:e|A|iOS)?\\/([0-9\\.]+)/ },\n { name: 'Samsung Browser', regex: /SamsungBrowser\\/([0-9\\.]+)/ },\n { name: 'Opera', regex: /(?:Opera|OPR)\\/([0-9\\.]+)/ },\n { name: 'Firefox', regex: /Firefox\\/([0-9\\.]+)/ },\n { name: 'Chrome', regex: /Chrome\\/([0-9\\.]+)/ },\n { name: 'Safari', regex: /Version\\/([0-9\\.]+).*Safari/ },\n { name: 'IE', regex: /MSIE|Trident/ }\n ];\n\n for (const browser of browsers) {\n const match = ua.match(browser.regex);\n if (match) {\n const version = match[1] || '';\n const major = version.split('.')[0] || '';\n\n // Engine detection\n let engine = 'Unknown';\n let engineVersion = '';\n \n if (ua.includes('AppleWebKit')) {\n const webkitMatch = ua.match(/AppleWebKit\\/([0-9\\.]+)/);\n engine = 'WebKit';\n engineVersion = webkitMatch ? webkitMatch[1] : '';\n } else if (ua.includes('Gecko')) {\n engine = 'Gecko';\n const geckoMatch = ua.match(/rv:([0-9\\.]+)/);\n engineVersion = geckoMatch ? geckoMatch[1] : '';\n } else if (ua.includes('Trident')) {\n engine = 'Trident';\n const tridentMatch = ua.match(/Trident\\/([0-9\\.]+)/);\n engineVersion = tridentMatch ? tridentMatch[1] : '';\n }\n \n return {\n name: browser.name,\n version,\n major,\n userAgent: ua,\n vendor,\n engine,\n engineVersion\n };\n }\n }\n\n return {\n name: 'Unknown',\n version: '',\n major: '',\n userAgent: ua,\n vendor,\n engine: 'Unknown',\n engineVersion: ''\n };\n };\n\n // OS detection\n const getOS = (): OSInfo => {\n const osMatchers = [\n { name: 'iOS', regex: /iPhone|iPad|iPod/ },\n { name: 'Android', regex: /Android ([0-9\\.]+)/ },\n { name: 'Windows', regex: /Windows NT ([0-9\\.]+)/ },\n { name: 'macOS', regex: /Mac OS X ([0-9_\\.]+)/ },\n { name: 'Linux', regex: /Linux/ }\n ];\n\n for (const os of osMatchers) {\n const match = ua.match(os.regex);\n if (match) {\n let version = '';\n if (match[1]) {\n version = os.name === 'macOS' \n ? match[1].replace(/_/g, '.') \n : match[1];\n }\n \n return {\n name: os.name,\n version,\n architecture: ua.includes('x64') || ua.includes('x86_64') ? '64-bit' : '32-bit'\n };\n }\n }\n\n return {\n name: 'Unknown',\n version: '',\n architecture: ua.includes('x64') || ua.includes('x86_64') ? '64-bit' : '32-bit'\n };\n };\n\n // Device detection\n const getDevice = (): DeviceInfo => {\n const isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);\n const isTablet = /iPad|Android(?!.*Mobile)/i.test(ua);\n \n let vendor = 'Unknown';\n let model = 'Unknown';\n \n if (ua.includes('iPhone') || ua.includes('iPad') || ua.includes('iPod')) {\n vendor = 'Apple';\n if (ua.includes('iPhone')) model = 'iPhone';\n if (ua.includes('iPad')) model = 'iPad';\n if (ua.includes('iPod')) model = 'iPod';\n } else if (ua.includes('Samsung')) {\n vendor = 'Samsung';\n } else if (ua.includes('Pixel')) {\n vendor = 'Google';\n const pixelMatch = ua.match(/Pixel ([0-9XL]+)/);\n if (pixelMatch) model = `Pixel ${pixelMatch[1]}`;\n }\n \n const deviceType = isTablet ? 'tablet' : (isMobileDevice ? 'mobile' : 'desktop');\n \n return {\n type: deviceType,\n vendor,\n model,\n orientation: innerHeight > innerWidth ? 'portrait' : 'landscape',\n isMobile: deviceType === 'mobile',\n isTablet: deviceType === 'tablet',\n isDesktop: deviceType === 'desktop',\n touch: maxTouchPoints > 0,\n };\n };\n\n return {\n browser: getBrowser(),\n os: getOS(),\n device: getDevice()\n };\n}","import { PerformanceInfo } from '../types/analytics';\n\n/**\n * Collects performance metrics from browser APIs\n */\nexport function getPerformanceInfo(): PerformanceInfo {\n const getNavigationInfo = () => {\n if (!window.performance || !window.performance.navigation) {\n return { type: 'Unknown', redirectCount: 0 };\n }\n \n const navTypes = ['navigate', 'reload', 'back_forward', 'prerender'];\n const navType = navTypes[window.performance.navigation.type] || 'Unknown';\n \n return {\n type: navType,\n redirectCount: window.performance.navigation.redirectCount\n };\n };\n\n const getTimingInfo = () => {\n if (!window.performance || !window.performance.timing) {\n return {\n loadTime: 0,\n domContentLoaded: 0,\n firstPaint: null,\n firstContentfulPaint: null\n };\n }\n\n const timing = window.performance.timing;\n const loadTime = timing.loadEventEnd - timing.navigationStart;\n const domContentLoaded = timing.domContentLoadedEventEnd - timing.navigationStart;\n\n // Get first paint and first contentful paint\n let firstPaint = null;\n let firstContentfulPaint = null;\n\n if (window.performance && typeof window.performance.getEntriesByType === 'function') {\n const paintMetrics = window.performance.getEntriesByType('paint');\n \n const fp = paintMetrics.find(entry => entry.name === 'first-paint');\n const fcp = paintMetrics.find(entry => entry.name === 'first-contentful-paint');\n \n if (fp) firstPaint = fp.startTime;\n if (fcp) firstContentfulPaint = fcp.startTime;\n }\n\n return {\n loadTime,\n domContentLoaded,\n firstPaint,\n firstContentfulPaint\n };\n };\n\n const getMemoryInfo = () => {\n // @ts-ignore: performance.memory is non-standard (Chrome only)\n if (window.performance && window.performance.memory) {\n // @ts-ignore\n const memory = window.performance.memory;\n return {\n jsHeapSizeLimit: memory.jsHeapSizeLimit,\n totalJSHeapSize: memory.totalJSHeapSize,\n usedJSHeapSize: memory.usedJSHeapSize\n };\n }\n return null;\n };\n\n return {\n memory: getMemoryInfo(),\n navigation: getNavigationInfo(),\n timing: getTimingInfo()\n };\n} ","import { NetworkInfo } from '../types/analytics';\n\n/**\n * Collects network information from browser APIs\n */\nexport function getNetworkInfo(): NetworkInfo {\n const online = typeof navigator !== 'undefined' ? navigator.onLine : false;\n \n // Default values\n let effectiveType = 'unknown';\n let downlink = 0;\n let rtt = 0;\n let saveData = false;\n\n // NetworkInformation API (limited browser support)\n // @ts-ignore: connection property is non-standard\n if (navigator && navigator.connection) {\n // @ts-ignore\n const connection = navigator.connection;\n \n effectiveType = connection.effectiveType || effectiveType;\n downlink = connection.downlink || downlink;\n rtt = connection.rtt || rtt;\n saveData = connection.saveData || saveData;\n }\n\n return {\n online,\n effectiveType,\n downlink,\n rtt,\n saveData\n };\n} ","import { ScreenInfo } from '../types/analytics';\n\n/**\n * Collects screen information from browser APIs\n */\nexport function getScreenInfo(): ScreenInfo {\n if (typeof window === 'undefined' || typeof screen === 'undefined') {\n return {\n width: 0,\n height: 0,\n availWidth: 0,\n availHeight: 0,\n colorDepth: 0,\n orientation: 'unknown',\n pixelRatio: 1,\n touchPoints: 0\n };\n }\n\n // Get screen orientation\n let orientation = 'unknown';\n if (window.innerHeight > window.innerWidth) {\n orientation = 'portrait';\n } else {\n orientation = 'landscape';\n }\n\n // Try to get more precise orientation if available\n // @ts-ignore: screen.orientation is non-standard\n if (screen.orientation && screen.orientation.type) {\n // @ts-ignore\n orientation = screen.orientation.type;\n }\n\n // Get pixel ratio\n const pixelRatio = window.devicePixelRatio || 1;\n\n // Get touch points\n const touchPoints = navigator.maxTouchPoints || 0;\n\n return {\n width: screen.width,\n height: screen.height,\n availWidth: screen.availWidth,\n availHeight: screen.availHeight,\n colorDepth: screen.colorDepth,\n orientation,\n pixelRatio,\n touchPoints\n };\n} ","import { LocationInfo } from '../types/analytics';\n\n/**\n * Collects location and environment information from browser APIs\n */\nexport function getLocationInfo(): LocationInfo {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') {\n return {\n timeZone: '',\n language: '',\n languages: [],\n isRestricted: false,\n doNotTrack: null,\n cookiesEnabled: false,\n localStorage: false,\n sessionStorage: false\n };\n }\n\n // Get timezone\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n // Get language info\n const language = navigator.language || '';\n const languages = navigator.languages ? Array.from(navigator.languages) : [language];\n\n // Check if window is restricted (e.g., iframe with restricted access)\n let isRestricted = false;\n try {\n isRestricted = window.self !== window.top;\n } catch (e) {\n isRestricted = true;\n }\n\n // Check Do Not Track setting\n let doNotTrack = null;\n if (navigator.doNotTrack === '1' || navigator.doNotTrack === 'yes') {\n doNotTrack = true;\n } else if (navigator.doNotTrack === '0' || navigator.doNotTrack === 'no') {\n doNotTrack = false;\n }\n\n // Check if cookies are enabled\n const cookiesEnabled = navigator.cookieEnabled;\n\n // Check for storage availability\n const checkStorage = (type: 'localStorage' | 'sessionStorage'): boolean => {\n try {\n const storage = window[type];\n const testKey = `__test_${type}__`;\n storage.setItem(testKey, 'test');\n storage.removeItem(testKey);\n return true;\n } catch (e) {\n return false;\n }\n };\n\n return {\n timeZone,\n language,\n languages,\n isRestricted,\n doNotTrack,\n cookiesEnabled,\n localStorage: checkStorage('localStorage'),\n sessionStorage: checkStorage('sessionStorage')\n };\n} ","/**\n * Schedules work during browser idle time to avoid blocking the main thread.\n * Falls back to setTimeout when requestIdleCallback is unavailable.\n */\nexport function scheduleIdle(callback: () => void | Promise<void>, timeout = 2000): void {\n if (typeof window === 'undefined') {\n void Promise.resolve().then(callback);\n return;\n }\n\n const run = (): void => {\n void Promise.resolve(callback());\n };\n\n if ('requestIdleCallback' in window) {\n window.requestIdleCallback(() => run(), { timeout });\n return;\n }\n\n setTimeout(run, 0);\n}\n","/**\n * Detects if the current browser is running in incognito/private mode\n */\nexport async function detectIncognito(): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n // First attempt: Test IndexedDB availability\n if (typeof window === 'undefined') {\n resolve(false);\n return;\n }\n\n const db = indexedDB.open('test');\n db.onerror = () => resolve(true);\n db.onsuccess = () => resolve(false);\n\n // Fallback: If no response after a timeout, assume not incognito\n setTimeout(() => resolve(false), 1000);\n });\n}\n\n/**\n * Checks for device media capabilities (camera/microphone)\n */\nexport async function checkMediaCapabilities(): Promise<{ \n hasCamera: boolean | null; \n hasMicrophone: boolean | null \n}> {\n if (typeof navigator === 'undefined' || !navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {\n return { hasCamera: null, hasMicrophone: null };\n }\n\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const hasCamera = devices.some(device => device.kind === 'videoinput');\n const hasMicrophone = devices.some(device => device.kind === 'audioinput');\n\n return { hasCamera, hasMicrophone };\n } catch (e) {\n return { hasCamera: null, hasMicrophone: null };\n }\n}\n\n/**\n * Checks for device battery status\n */\nexport async function getBatteryInfo(): Promise<{\n hasBattery: boolean | null;\n level: number | null;\n charging: boolean | null;\n}> {\n // @ts-ignore: getBattery method is non-standard\n if (typeof navigator === 'undefined' || !navigator.getBattery) {\n return { hasBattery: null, level: null, charging: null };\n }\n\n try {\n // @ts-ignore\n const battery = await navigator.getBattery();\n return {\n hasBattery: true,\n level: battery.level,\n charging: battery.charging\n };\n } catch (e) {\n return { hasBattery: null, level: null, charging: null };\n }\n}\n\n/**\n * Checks permission status for various browser features\n */\nexport async function checkPermissions(): Promise<Record<string, string>> {\n if (typeof navigator === 'undefined' || !navigator.permissions || !navigator.permissions.query) {\n return {};\n }\n\n const permissions: Record<string, string> = {};\n const featuresToCheck = [\n 'geolocation',\n 'notifications',\n 'push',\n 'midi',\n 'camera',\n 'microphone',\n 'background-sync',\n 'accelerometer',\n 'gyroscope',\n 'magnetometer',\n ];\n\n const results = await Promise.all(\n featuresToCheck.map(async (feature) => {\n try {\n const result = await navigator.permissions!.query({ name: feature as PermissionName });\n return [feature, result.state] as const;\n } catch {\n return [feature, 'not-supported'] as const;\n }\n }),\n );\n\n for (const [feature, state] of results) {\n permissions[feature] = state;\n }\n\n return permissions;\n} ","import { SoloAnalyticsInfo } from '../types/analytics';\n\nimport { parseUserAgent } from '../utils/parseUserAgent';\nimport { getPerformanceInfo } from '../utils/performance';\nimport { getNetworkInfo } from '../utils/network';\nimport { getScreenInfo } from '../utils/screen';\nimport { getLocationInfo } from '../utils/location';\nimport { scheduleIdle } from '../utils/scheduleIdle';\nimport {\n detectIncognito,\n checkMediaCapabilities,\n getBatteryInfo,\n checkPermissions,\n} from '../utils/features';\n\n/**\n * Type definition for analytics options\n */\nexport interface SoloAnalyticsOptions {\n /** Automatically refresh dynamic data (network, performance) */\n autoRefresh?: boolean;\n /** Refresh interval in milliseconds (default: 30000) */\n refreshInterval?: number;\n /** Track page visibility changes */\n trackVisibility?: boolean;\n /**\n * Run expensive async probes (incognito, battery, media, permissions).\n * Set to `false` to skip entirely and reduce main-thread work.\n * @default true\n */\n detectFeatures?: boolean;\n /**\n * Defer async feature probes to idle time via requestIdleCallback.\n * Sync data (UA, screen, network) is collected immediately.\n * @default true\n */\n lazyFeatures?: boolean;\n}\n\n/**\n * Type definition for the return value of useSoloAnalytics\n */\nexport interface SoloAnalyticsReturn {\n data: SoloAnalyticsInfo;\n refresh: () => Promise<void>;\n isMobile: boolean;\n isTablet: boolean;\n isDesktop: boolean;\n isOnline: boolean;\n isVisible: boolean;\n browserName: string;\n osName: string;\n destroy: () => void;\n}\n\nconst createInitialData = (): SoloAnalyticsInfo => ({\n browser: {\n name: '',\n version: '',\n major: '',\n userAgent: '',\n vendor: '',\n engine: '',\n engineVersion: '',\n },\n os: {\n name: '',\n version: '',\n architecture: '',\n },\n device: {\n type: 'unknown',\n vendor: '',\n model: '',\n orientation: 'portrait',\n isMobile: false,\n isTablet: false,\n isDesktop: false,\n touch: false,\n },\n network: {\n online: false,\n effectiveType: '',\n downlink: 0,\n rtt: 0,\n saveData: false,\n },\n screen: {\n width: 0,\n height: 0,\n availWidth: 0,\n availHeight: 0,\n colorDepth: 0,\n orientation: '',\n pixelRatio: 1,\n touchPoints: 0,\n },\n performance: {\n memory: null,\n navigation: {\n type: '',\n redirectCount: 0,\n },\n timing: {\n loadTime: 0,\n domContentLoaded: 0,\n firstPaint: null,\n firstContentfulPaint: null,\n },\n },\n location: {\n timeZone: '',\n language: '',\n languages: [],\n isRestricted: false,\n doNotTrack: null,\n cookiesEnabled: false,\n localStorage: false,\n sessionStorage: false,\n },\n pageVisibility: 'visible',\n referrer: '',\n isIncognito: false,\n hasCamera: null,\n hasMicrophone: null,\n hasBattery: null,\n batteryLevel: null,\n batteryCharging: null,\n permissions: {},\n});\n\n/**\n * A function that provides comprehensive browser, device, and performance analytics.\n * @param options Configuration options\n * @returns Object with analytics data and helper methods\n */\nexport function useSoloAnalytics(options: SoloAnalyticsOptions = {}): SoloAnalyticsReturn {\n const {\n autoRefresh = false,\n refreshInterval = 30000,\n trackVisibility = true,\n detectFeatures = true,\n lazyFeatures = true,\n } = options;\n\n const analyticsData = createInitialData();\n\n let visibilityChangeListener: (() => void) | null = null;\n let refreshTimer: ReturnType<typeof setInterval> | null = null;\n let destroyed = false;\n\n const collectSyncData = (): void => {\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\n return;\n }\n\n const userAgent = navigator.userAgent;\n const { browser, os, device } = parseUserAgent(userAgent);\n\n Object.assign(analyticsData, {\n browser,\n os,\n device,\n screen: getScreenInfo(),\n location: getLocationInfo(),\n referrer: document.referrer,\n });\n };\n\n const collectAsyncFeatures = async (): Promise<void> => {\n if (!detectFeatures || destroyed) {\n return;\n }\n\n const [isIncognito, media, battery, permissions] = await Promise.all([\n detectIncognito(),\n checkMediaCapabilities(),\n getBatteryInfo(),\n checkPermissions(),\n ]);\n\n if (destroyed) {\n return;\n }\n\n Object.assign(analyticsData, {\n isIncognito,\n hasCamera: media.hasCamera,\n hasMicrophone: media.hasMicrophone,\n hasBattery: battery.hasBattery,\n batteryLevel: battery.level,\n batteryCharging: battery.charging,\n permissions,\n });\n };\n\n const collectDynamicData = (): void => {\n if (typeof navigator === 'undefined' || typeof window === 'undefined') {\n return;\n }\n\n Object.assign(analyticsData, {\n network: getNetworkInfo(),\n performance: getPerformanceInfo(),\n pageVisibility: document.visibilityState === 'visible' ? 'visible' : 'hidden',\n });\n };\n\n const runFeatureDetection = (): void => {\n if (!detectFeatures) {\n return;\n }\n\n const run = (): void => {\n void collectAsyncFeatures();\n };\n\n if (lazyFeatures) {\n scheduleIdle(run);\n return;\n }\n\n run();\n };\n\n if (trackVisibility && typeof document !== 'undefined') {\n const handleVisibilityChange = (): void => {\n analyticsData.pageVisibility =\n document.visibilityState === 'visible' ? 'visible' : 'hidden';\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n visibilityChangeListener = handleVisibilityChange;\n }\n\n if (autoRefresh && typeof window !== 'undefined') {\n refreshTimer = setInterval(collectDynamicData, refreshInterval);\n }\n\n const init = (): void => {\n collectSyncData();\n collectDynamicData();\n runFeatureDetection();\n };\n\n init();\n\n const refresh = async (): Promise<void> => {\n collectSyncData();\n collectDynamicData();\n await collectAsyncFeatures();\n };\n\n const destroy = (): void => {\n destroyed = true;\n\n if (refreshTimer !== null) {\n clearInterval(refreshTimer);\n refreshTimer = null;\n }\n\n if (visibilityChangeListener && typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', visibilityChangeListener);\n visibilityChangeListener = null;\n }\n };\n\n return {\n data: analyticsData,\n refresh,\n destroy,\n get isMobile(): boolean {\n return analyticsData.device.isMobile;\n },\n get isTablet(): boolean {\n return analyticsData.device.isTablet;\n },\n get isDesktop(): boolean {\n return analyticsData.device.isDesktop;\n },\n get isOnline(): boolean {\n return analyticsData.network.online;\n },\n get isVisible(): boolean {\n return analyticsData.pageVisibility === 'visible';\n },\n get browserName(): string {\n return analyticsData.browser.name;\n },\n get osName(): string {\n return analyticsData.os.name;\n },\n };\n}\n"],"names":["parseUserAgent","ua","options","vendor","innerWidth","innerHeight","maxTouchPoints","getBrowser","browsers","browser","match","version","major","engine","engineVersion","webkitMatch","geckoMatch","tridentMatch","getOS","osMatchers","os","getDevice","isMobileDevice","isTablet","model","pixelMatch","deviceType","getPerformanceInfo","getNavigationInfo","getTimingInfo","timing","loadTime","domContentLoaded","firstPaint","firstContentfulPaint","paintMetrics","fp","entry","fcp","memory","getNetworkInfo","online","effectiveType","downlink","rtt","saveData","connection","getScreenInfo","orientation","pixelRatio","touchPoints","getLocationInfo","timeZone","language","languages","isRestricted","doNotTrack","cookiesEnabled","checkStorage","type","storage","testKey","scheduleIdle","callback","timeout","run","detectIncognito","resolve","db","checkMediaCapabilities","devices","hasCamera","device","hasMicrophone","getBatteryInfo","battery","checkPermissions","permissions","featuresToCheck","results","feature","result","state","createInitialData","useSoloAnalytics","autoRefresh","refreshInterval","trackVisibility","detectFeatures","lazyFeatures","analyticsData","visibilityChangeListener","refreshTimer","destroyed","collectSyncData","userAgent","collectAsyncFeatures","isIncognito","media","collectDynamicData","runFeatureDetection","handleVisibilityChange"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- (function(v,w){typeof exports=="object"&&typeof module<"u"?w(exports):typeof define=="function"&&define.amd?define(["exports"],w):(v=typeof globalThis<"u"?globalThis:v||self,w(v.SoloAnalytics={}))})(this,function(v){"use strict";function w(e,t={}){const i=t.vendor??(typeof navigator<"u"?navigator.vendor:""),n=t.innerWidth??(typeof window<"u"?window.innerWidth:1024),r=t.innerHeight??(typeof window<"u"?window.innerHeight:768),u=t.maxTouchPoints??(typeof navigator<"u"&&"maxTouchPoints"in navigator?navigator.maxTouchPoints:0),o=()=>{const s=[{name:"Edge",regex:/Edg(?:e|A|iOS)?\/([0-9\.]+)/},{name:"Samsung Browser",regex:/SamsungBrowser\/([0-9\.]+)/},{name:"Opera",regex:/(?:Opera|OPR)\/([0-9\.]+)/},{name:"Firefox",regex:/Firefox\/([0-9\.]+)/},{name:"Chrome",regex:/Chrome\/([0-9\.]+)/},{name:"Safari",regex:/Version\/([0-9\.]+).*Safari/},{name:"IE",regex:/MSIE|Trident/}];for(const l of s){const a=e.match(l.regex);if(a){const c=a[1]||"",p=c.split(".")[0]||"";let h="Unknown",y="";if(e.includes("AppleWebKit")){const g=e.match(/AppleWebKit\/([0-9\.]+)/);h="WebKit",y=g?g[1]:""}else if(e.includes("Gecko")){h="Gecko";const g=e.match(/rv:([0-9\.]+)/);y=g?g[1]:""}else if(e.includes("Trident")){h="Trident";const g=e.match(/Trident\/([0-9\.]+)/);y=g?g[1]:""}return{name:l.name,version:c,major:p,userAgent:e,vendor:i,engine:h,engineVersion:y}}}return{name:"Unknown",version:"",major:"",userAgent:e,vendor:i,engine:"Unknown",engineVersion:""}},d=()=>{const s=[{name:"iOS",regex:/iPhone|iPad|iPod/},{name:"Android",regex:/Android ([0-9\.]+)/},{name:"Windows",regex:/Windows NT ([0-9\.]+)/},{name:"macOS",regex:/Mac OS X ([0-9_\.]+)/},{name:"Linux",regex:/Linux/}];for(const l of s){const a=e.match(l.regex);if(a){let c="";return a[1]&&(c=l.name==="macOS"?a[1].replace(/_/g,"."):a[1]),{name:l.name,version:c,architecture:e.includes("x64")||e.includes("x86_64")?"64-bit":"32-bit"}}}return{name:"Unknown",version:"",architecture:e.includes("x64")||e.includes("x86_64")?"64-bit":"32-bit"}},f=()=>{const s=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e),l=/iPad|Android(?!.*Mobile)/i.test(e);let a="Unknown",c="Unknown";if(e.includes("iPhone")||e.includes("iPad")||e.includes("iPod"))a="Apple",e.includes("iPhone")&&(c="iPhone"),e.includes("iPad")&&(c="iPad"),e.includes("iPod")&&(c="iPod");else if(e.includes("Samsung"))a="Samsung";else if(e.includes("Pixel")){a="Google";const h=e.match(/Pixel ([0-9XL]+)/);h&&(c=`Pixel ${h[1]}`)}const p=l?"tablet":s?"mobile":"desktop";return{type:p,vendor:a,model:c,orientation:r>n?"portrait":"landscape",isMobile:p==="mobile",isTablet:p==="tablet",isDesktop:p==="desktop",touch:u>0}};return{browser:o(),os:d(),device:f()}}function S(){const e=()=>!window.performance||!window.performance.navigation?{type:"Unknown",redirectCount:0}:{type:["navigate","reload","back_forward","prerender"][window.performance.navigation.type]||"Unknown",redirectCount:window.performance.navigation.redirectCount},t=()=>{if(!window.performance||!window.performance.timing)return{loadTime:0,domContentLoaded:0,firstPaint:null,firstContentfulPaint:null};const n=window.performance.timing,r=n.loadEventEnd-n.navigationStart,u=n.domContentLoadedEventEnd-n.navigationStart;let o=null,d=null;if(window.performance&&typeof window.performance.getEntriesByType=="function"){const f=window.performance.getEntriesByType("paint"),s=f.find(a=>a.name==="first-paint"),l=f.find(a=>a.name==="first-contentful-paint");s&&(o=s.startTime),l&&(d=l.startTime)}return{loadTime:r,domContentLoaded:u,firstPaint:o,firstContentfulPaint:d}};return{memory:(()=>{if(window.performance&&window.performance.memory){const n=window.performance.memory;return{jsHeapSizeLimit:n.jsHeapSizeLimit,totalJSHeapSize:n.totalJSHeapSize,usedJSHeapSize:n.usedJSHeapSize}}return null})(),navigation:e(),timing:t()}}function P(){const e=typeof navigator<"u"?navigator.onLine:!1;let t="unknown",i=0,n=0,r=!1;if(navigator&&navigator.connection){const u=navigator.connection;t=u.effectiveType||t,i=u.downlink||i,n=u.rtt||n,r=u.saveData||r}return{online:e,effectiveType:t,downlink:i,rtt:n,saveData:r}}function x(){if(typeof window>"u"||typeof screen>"u")return{width:0,height:0,availWidth:0,availHeight:0,colorDepth:0,orientation:"unknown",pixelRatio:1,touchPoints:0};let e="unknown";window.innerHeight>window.innerWidth?e="portrait":e="landscape",screen.orientation&&screen.orientation.type&&(e=screen.orientation.type);const t=window.devicePixelRatio||1,i=navigator.maxTouchPoints||0;return{width:screen.width,height:screen.height,availWidth:screen.availWidth,availHeight:screen.availHeight,colorDepth:screen.colorDepth,orientation:e,pixelRatio:t,touchPoints:i}}function C(){if(typeof window>"u"||typeof navigator>"u")return{timeZone:"",language:"",languages:[],isRestricted:!1,doNotTrack:null,cookiesEnabled:!1,localStorage:!1,sessionStorage:!1};const e=Intl.DateTimeFormat().resolvedOptions().timeZone,t=navigator.language||"",i=navigator.languages?Array.from(navigator.languages):[t];let n=!1;try{n=window.self!==window.top}catch{n=!0}let r=null;navigator.doNotTrack==="1"||navigator.doNotTrack==="yes"?r=!0:(navigator.doNotTrack==="0"||navigator.doNotTrack==="no")&&(r=!1);const u=navigator.cookieEnabled,o=d=>{try{const f=window[d],s=`__test_${d}__`;return f.setItem(s,"test"),f.removeItem(s),!0}catch{return!1}};return{timeZone:e,language:t,languages:i,isRestricted:n,doNotTrack:r,cookiesEnabled:u,localStorage:o("localStorage"),sessionStorage:o("sessionStorage")}}function D(e,t=2e3){if(typeof window>"u"){Promise.resolve().then(e);return}const i=()=>{Promise.resolve(e())};if("requestIdleCallback"in window){window.requestIdleCallback(()=>i(),{timeout:t});return}setTimeout(i,0)}async function M(){return new Promise(e=>{if(typeof window>"u"){e(!1);return}const t=indexedDB.open("test");t.onerror=()=>e(!0),t.onsuccess=()=>e(!1),setTimeout(()=>e(!1),1e3)})}async function I(){if(typeof navigator>"u"||!navigator.mediaDevices||!navigator.mediaDevices.enumerateDevices)return{hasCamera:null,hasMicrophone:null};try{const e=await navigator.mediaDevices.enumerateDevices(),t=e.some(n=>n.kind==="videoinput"),i=e.some(n=>n.kind==="audioinput");return{hasCamera:t,hasMicrophone:i}}catch{return{hasCamera:null,hasMicrophone:null}}}async function A(){if(typeof navigator>"u"||!navigator.getBattery)return{hasBattery:null,level:null,charging:null};try{const e=await navigator.getBattery();return{hasBattery:!0,level:e.level,charging:e.charging}}catch{return{hasBattery:null,level:null,charging:null}}}async function B(){if(typeof navigator>"u"||!navigator.permissions||!navigator.permissions.query)return{};const e={},t=["geolocation","notifications","push","midi","camera","microphone","background-sync","accelerometer","gyroscope","magnetometer"],i=await Promise.all(t.map(async n=>{try{const r=await navigator.permissions.query({name:n});return[n,r.state]}catch{return[n,"not-supported"]}}));for(const[n,r]of i)e[n]=r;return e}const E=()=>({browser:{name:"",version:"",major:"",userAgent:"",vendor:"",engine:"",engineVersion:""},os:{name:"",version:"",architecture:""},device:{type:"unknown",vendor:"",model:"",orientation:"portrait",isMobile:!1,isTablet:!1,isDesktop:!1,touch:!1},network:{online:!1,effectiveType:"",downlink:0,rtt:0,saveData:!1},screen:{width:0,height:0,availWidth:0,availHeight:0,colorDepth:0,orientation:"",pixelRatio:1,touchPoints:0},performance:{memory:null,navigation:{type:"",redirectCount:0},timing:{loadTime:0,domContentLoaded:0,firstPaint:null,firstContentfulPaint:null}},location:{timeZone:"",language:"",languages:[],isRestricted:!1,doNotTrack:null,cookiesEnabled:!1,localStorage:!1,sessionStorage:!1},pageVisibility:"visible",referrer:"",isIncognito:!1,hasCamera:null,hasMicrophone:null,hasBattery:null,batteryLevel:null,batteryCharging:null,permissions:{}});function O(e={}){const{autoRefresh:t=!1,refreshInterval:i=3e4,trackVisibility:n=!0,detectFeatures:r=!0,lazyFeatures:u=!0}=e,o=E();let d=null,f=null,s=!1;const l=()=>{if(typeof navigator>"u"||typeof window>"u")return;const m=navigator.userAgent,{browser:k,os:b,device:T}=w(m);Object.assign(o,{browser:k,os:b,device:T,screen:x(),location:C(),referrer:document.referrer})},a=async()=>{if(!r||s)return;const[m,k,b,T]=await Promise.all([M(),I(),A(),B()]);s||Object.assign(o,{isIncognito:m,hasCamera:k.hasCamera,hasMicrophone:k.hasMicrophone,hasBattery:b.hasBattery,batteryLevel:b.level,batteryCharging:b.charging,permissions:T})},c=()=>{typeof navigator>"u"||typeof window>"u"||Object.assign(o,{network:P(),performance:S(),pageVisibility:document.visibilityState==="visible"?"visible":"hidden"})},p=()=>{if(!r)return;const m=()=>{a()};if(u){D(m);return}m()};if(n&&typeof document<"u"){const m=()=>{o.pageVisibility=document.visibilityState==="visible"?"visible":"hidden"};document.addEventListener("visibilitychange",m),d=m}return t&&typeof window<"u"&&(f=setInterval(c,i)),(()=>{l(),c(),p()})(),{data:o,refresh:async()=>{l(),c(),await a()},destroy:()=>{s=!0,f!==null&&(clearInterval(f),f=null),d&&typeof document<"u"&&(document.removeEventListener("visibilitychange",d),d=null)},get isMobile(){return o.device.isMobile},get isTablet(){return o.device.isTablet},get isDesktop(){return o.device.isDesktop},get isOnline(){return o.network.online},get isVisible(){return o.pageVisibility==="visible"},get browserName(){return o.browser.name},get osName(){return o.os.name}}}v.useSoloAnalytics=O,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"})});
2
- //# sourceMappingURL=solo-analytics.umd.cjs.map