@shware/analytics 2.17.2 → 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/{use-screen-view-analytics.cjs → use-app-analytics.cjs} +30 -31
- package/dist/hooks/use-app-analytics.cjs.map +1 -0
- package/dist/hooks/use-app-analytics.d.cts +3 -0
- package/dist/hooks/use-app-analytics.d.ts +3 -0
- package/dist/hooks/use-app-analytics.mjs +50 -0
- package/dist/hooks/use-app-analytics.mjs.map +1 -0
- package/dist/hooks/use-outbound-click-analytics.cjs +58 -0
- package/dist/hooks/use-outbound-click-analytics.cjs.map +1 -0
- package/dist/hooks/use-outbound-click-analytics.d.cts +7 -0
- package/dist/hooks/use-outbound-click-analytics.d.ts +7 -0
- package/dist/hooks/use-outbound-click-analytics.mjs +33 -0
- package/dist/hooks/use-outbound-click-analytics.mjs.map +1 -0
- package/dist/hooks/use-web-analytics.cjs +128 -0
- package/dist/hooks/use-web-analytics.cjs.map +1 -0
- package/dist/hooks/{use-web-session-analytics.d.cts → use-web-analytics.d.cts} +2 -2
- package/dist/hooks/{use-web-session-analytics.d.ts → use-web-analytics.d.ts} +2 -2
- package/dist/hooks/use-web-analytics.mjs +103 -0
- package/dist/hooks/use-web-analytics.mjs.map +1 -0
- package/dist/native/index.cjs +3 -6
- package/dist/native/index.cjs.map +1 -1
- package/dist/native/index.d.cts +1 -2
- package/dist/native/index.d.ts +1 -2
- package/dist/native/index.mjs +2 -4
- package/dist/native/index.mjs.map +1 -1
- package/dist/next/index.cjs +4 -4
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.mjs +4 -4
- package/dist/next/index.mjs.map +1 -1
- package/dist/react-router/index.cjs +4 -4
- package/dist/react-router/index.cjs.map +1 -1
- package/dist/react-router/index.mjs +4 -4
- package/dist/react-router/index.mjs.map +1 -1
- package/dist/setup/session.cjs +77 -22
- package/dist/setup/session.cjs.map +1 -1
- package/dist/setup/session.d.cts +27 -9
- package/dist/setup/session.d.ts +27 -9
- package/dist/setup/session.mjs +76 -18
- package/dist/setup/session.mjs.map +1 -1
- package/dist/track/gtag.cjs.map +1 -1
- package/dist/track/gtag.d.cts +1 -2
- package/dist/track/gtag.d.ts +1 -2
- package/dist/track/gtag.mjs.map +1 -1
- package/dist/track/index.cjs +6 -8
- package/dist/track/index.cjs.map +1 -1
- package/dist/track/index.mjs +7 -14
- package/dist/track/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/hooks/use-app-session-analytics.cjs +0 -68
- package/dist/hooks/use-app-session-analytics.cjs.map +0 -1
- package/dist/hooks/use-app-session-analytics.d.cts +0 -3
- package/dist/hooks/use-app-session-analytics.d.ts +0 -3
- package/dist/hooks/use-app-session-analytics.mjs +0 -43
- package/dist/hooks/use-app-session-analytics.mjs.map +0 -1
- package/dist/hooks/use-page-view-analytics.cjs +0 -82
- package/dist/hooks/use-page-view-analytics.cjs.map +0 -1
- package/dist/hooks/use-page-view-analytics.d.cts +0 -3
- package/dist/hooks/use-page-view-analytics.d.ts +0 -3
- package/dist/hooks/use-page-view-analytics.mjs +0 -57
- package/dist/hooks/use-page-view-analytics.mjs.map +0 -1
- package/dist/hooks/use-screen-view-analytics.cjs.map +0 -1
- package/dist/hooks/use-screen-view-analytics.d.cts +0 -3
- package/dist/hooks/use-screen-view-analytics.d.ts +0 -3
- package/dist/hooks/use-screen-view-analytics.mjs +0 -51
- package/dist/hooks/use-screen-view-analytics.mjs.map +0 -1
- package/dist/hooks/use-web-session-analytics.cjs +0 -137
- package/dist/hooks/use-web-session-analytics.cjs.map +0 -1
- package/dist/hooks/use-web-session-analytics.mjs +0 -112
- package/dist/hooks/use-web-session-analytics.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-app-session-analytics.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { track } from '../track/index';\n\nexport function useAppSessionAnalytics() {\n const isActive = useRef(true);\n const startTime = useRef(Date.now());\n const accumulatedTime = useRef(0);\n\n const updateAccumulator = useCallback(() => {\n const now = Date.now();\n if (isActive.current) {\n const delta = now - startTime.current;\n if (delta > 0) {\n accumulatedTime.current += delta;\n }\n }\n startTime.current = now;\n }, []);\n\n const sendUserEngagement = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n track('user_engagement', { engagement_time_msec }, { enableThirdPartyTracking: false });\n }, [updateAccumulator]);\n\n useEffect(() => {\n track('session_start', undefined, { enableThirdPartyTracking: false });\n\n const subscription = AppState.addEventListener('change', (state) => {\n updateAccumulator();\n // when returning to the foreground from the background\n if (state === 'active' && !isActive.current) {\n isActive.current = true;\n }\n // when entering the background\n else if (state !== 'active' && isActive.current) {\n isActive.current = false;\n sendUserEngagement();\n }\n });\n\n return () => subscription.remove();\n }, []);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+C;AAC/C,0BAAyB;AACzB,mBAAsB;AAEf,SAAS,yBAAyB;AACvC,QAAM,eAAW,qBAAO,IAAI;AAC5B,QAAM,gBAAY,qBAAO,KAAK,IAAI,CAAC;AACnC,QAAM,sBAAkB,qBAAO,CAAC;AAEhC,QAAM,wBAAoB,0BAAY,MAAM;AAC1C,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,SAAS,SAAS;AACpB,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,QAAQ,GAAG;AACb,wBAAgB,WAAW;AAAA,MAC7B;AAAA,IACF;AACA,cAAU,UAAU;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAqB,0BAAY,MAAM;AAC3C,sBAAkB;AAClB,UAAM,uBAAuB,gBAAgB;AAC7C,oBAAgB,UAAU;AAC1B,QAAI,wBAAwB,EAAG;AAC/B,4BAAM,mBAAmB,EAAE,qBAAqB,GAAG,EAAE,0BAA0B,MAAM,CAAC;AAAA,EACxF,GAAG,CAAC,iBAAiB,CAAC;AAEtB,8BAAU,MAAM;AACd,4BAAM,iBAAiB,QAAW,EAAE,0BAA0B,MAAM,CAAC;AAErE,UAAM,eAAe,6BAAS,iBAAiB,UAAU,CAAC,UAAU;AAClE,wBAAkB;AAElB,UAAI,UAAU,YAAY,CAAC,SAAS,SAAS;AAC3C,iBAAS,UAAU;AAAA,MACrB,WAES,UAAU,YAAY,SAAS,SAAS;AAC/C,iBAAS,UAAU;AACnB,2BAAmB;AAAA,MACrB;AAAA,IACF,CAAC;AAED,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,CAAC;AACP;","names":[]}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// src/hooks/use-app-session-analytics.ts
|
|
2
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
3
|
-
import { AppState } from "react-native";
|
|
4
|
-
import { track } from "../track/index.mjs";
|
|
5
|
-
function useAppSessionAnalytics() {
|
|
6
|
-
const isActive = useRef(true);
|
|
7
|
-
const startTime = useRef(Date.now());
|
|
8
|
-
const accumulatedTime = useRef(0);
|
|
9
|
-
const updateAccumulator = useCallback(() => {
|
|
10
|
-
const now = Date.now();
|
|
11
|
-
if (isActive.current) {
|
|
12
|
-
const delta = now - startTime.current;
|
|
13
|
-
if (delta > 0) {
|
|
14
|
-
accumulatedTime.current += delta;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
startTime.current = now;
|
|
18
|
-
}, []);
|
|
19
|
-
const sendUserEngagement = useCallback(() => {
|
|
20
|
-
updateAccumulator();
|
|
21
|
-
const engagement_time_msec = accumulatedTime.current;
|
|
22
|
-
accumulatedTime.current = 0;
|
|
23
|
-
if (engagement_time_msec <= 0) return;
|
|
24
|
-
track("user_engagement", { engagement_time_msec }, { enableThirdPartyTracking: false });
|
|
25
|
-
}, [updateAccumulator]);
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
track("session_start", void 0, { enableThirdPartyTracking: false });
|
|
28
|
-
const subscription = AppState.addEventListener("change", (state) => {
|
|
29
|
-
updateAccumulator();
|
|
30
|
-
if (state === "active" && !isActive.current) {
|
|
31
|
-
isActive.current = true;
|
|
32
|
-
} else if (state !== "active" && isActive.current) {
|
|
33
|
-
isActive.current = false;
|
|
34
|
-
sendUserEngagement();
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
return () => subscription.remove();
|
|
38
|
-
}, []);
|
|
39
|
-
}
|
|
40
|
-
export {
|
|
41
|
-
useAppSessionAnalytics
|
|
42
|
-
};
|
|
43
|
-
//# sourceMappingURL=use-app-session-analytics.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-app-session-analytics.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { track } from '../track/index';\n\nexport function useAppSessionAnalytics() {\n const isActive = useRef(true);\n const startTime = useRef(Date.now());\n const accumulatedTime = useRef(0);\n\n const updateAccumulator = useCallback(() => {\n const now = Date.now();\n if (isActive.current) {\n const delta = now - startTime.current;\n if (delta > 0) {\n accumulatedTime.current += delta;\n }\n }\n startTime.current = now;\n }, []);\n\n const sendUserEngagement = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n track('user_engagement', { engagement_time_msec }, { enableThirdPartyTracking: false });\n }, [updateAccumulator]);\n\n useEffect(() => {\n track('session_start', undefined, { enableThirdPartyTracking: false });\n\n const subscription = AppState.addEventListener('change', (state) => {\n updateAccumulator();\n // when returning to the foreground from the background\n if (state === 'active' && !isActive.current) {\n isActive.current = true;\n }\n // when entering the background\n else if (state !== 'active' && isActive.current) {\n isActive.current = false;\n sendUserEngagement();\n }\n });\n\n return () => subscription.remove();\n }, []);\n}\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,gBAAgB;AACzB,SAAS,aAAa;AAEf,SAAS,yBAAyB;AACvC,QAAM,WAAW,OAAO,IAAI;AAC5B,QAAM,YAAY,OAAO,KAAK,IAAI,CAAC;AACnC,QAAM,kBAAkB,OAAO,CAAC;AAEhC,QAAM,oBAAoB,YAAY,MAAM;AAC1C,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,SAAS,SAAS;AACpB,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,QAAQ,GAAG;AACb,wBAAgB,WAAW;AAAA,MAC7B;AAAA,IACF;AACA,cAAU,UAAU;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,YAAY,MAAM;AAC3C,sBAAkB;AAClB,UAAM,uBAAuB,gBAAgB;AAC7C,oBAAgB,UAAU;AAC1B,QAAI,wBAAwB,EAAG;AAC/B,UAAM,mBAAmB,EAAE,qBAAqB,GAAG,EAAE,0BAA0B,MAAM,CAAC;AAAA,EACxF,GAAG,CAAC,iBAAiB,CAAC;AAEtB,YAAU,MAAM;AACd,UAAM,iBAAiB,QAAW,EAAE,0BAA0B,MAAM,CAAC;AAErE,UAAM,eAAe,SAAS,iBAAiB,UAAU,CAAC,UAAU;AAClE,wBAAkB;AAElB,UAAI,UAAU,YAAY,CAAC,SAAS,SAAS;AAC3C,iBAAS,UAAU;AAAA,MACrB,WAES,UAAU,YAAY,SAAS,SAAS;AAC/C,iBAAS,UAAU;AACnB,2BAAmB;AAAA,MACrB;AAAA,IACF,CAAC;AAED,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,CAAC;AACP;","names":[]}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/hooks/use-page-view-analytics.ts
|
|
21
|
-
var use_page_view_analytics_exports = {};
|
|
22
|
-
__export(use_page_view_analytics_exports, {
|
|
23
|
-
usePageViewAnalytics: () => usePageViewAnalytics
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(use_page_view_analytics_exports);
|
|
26
|
-
var import_react = require("react");
|
|
27
|
-
var import_setup = require("../setup/index.cjs");
|
|
28
|
-
var import_track = require("../track/index.cjs");
|
|
29
|
-
var import_use_previous = require("./use-previous.cjs");
|
|
30
|
-
function usePageViewAnalytics(pathname) {
|
|
31
|
-
const prevPathname = (0, import_use_previous.usePrevious)(pathname);
|
|
32
|
-
const session = (0, import_react.useRef)({ start: performance.now(), total: 0, isActive: true });
|
|
33
|
-
(0, import_react.useEffect)(() => {
|
|
34
|
-
const handler = () => {
|
|
35
|
-
if (document.hidden) {
|
|
36
|
-
session.current.total += (performance.now() - session.current.start) / 1e3;
|
|
37
|
-
session.current.isActive = false;
|
|
38
|
-
} else {
|
|
39
|
-
session.current.start = performance.now();
|
|
40
|
-
session.current.isActive = true;
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
document.addEventListener("visibilitychange", handler);
|
|
44
|
-
return () => document.removeEventListener("visibilitychange", handler);
|
|
45
|
-
}, []);
|
|
46
|
-
(0, import_react.useEffect)(() => {
|
|
47
|
-
const key = "first_visit_time";
|
|
48
|
-
if (import_setup.config.storage.getItem(key)) return;
|
|
49
|
-
const properties = {
|
|
50
|
-
page_path: pathname,
|
|
51
|
-
page_title: document.title,
|
|
52
|
-
page_referrer: document.referrer,
|
|
53
|
-
page_location: window.location.href
|
|
54
|
-
};
|
|
55
|
-
(0, import_track.track)("first_visit", properties, { enableThirdPartyTracking: false });
|
|
56
|
-
import_setup.config.storage.setItem(key, (/* @__PURE__ */ new Date()).toISOString());
|
|
57
|
-
}, []);
|
|
58
|
-
(0, import_react.useEffect)(() => {
|
|
59
|
-
if (!prevPathname) {
|
|
60
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
61
|
-
}
|
|
62
|
-
let duration = session.current.total;
|
|
63
|
-
if (session.current.isActive) {
|
|
64
|
-
duration += (performance.now() - session.current.start) / 1e3;
|
|
65
|
-
}
|
|
66
|
-
const properties = {
|
|
67
|
-
page_path: pathname,
|
|
68
|
-
page_title: document.title,
|
|
69
|
-
page_referrer: document.referrer,
|
|
70
|
-
page_location: window.location.href,
|
|
71
|
-
previous_page_path: prevPathname ?? void 0,
|
|
72
|
-
previous_page_path_duration: prevPathname ? Number(duration.toFixed(2)) : void 0
|
|
73
|
-
};
|
|
74
|
-
(0, import_track.track)("page_view", properties, { enableThirdPartyTracking: false });
|
|
75
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
76
|
-
}, [pathname]);
|
|
77
|
-
}
|
|
78
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
79
|
-
0 && (module.exports = {
|
|
80
|
-
usePageViewAnalytics
|
|
81
|
-
});
|
|
82
|
-
//# sourceMappingURL=use-page-view-analytics.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-page-view-analytics.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { config } from '../setup/index';\nimport { track } from '../track/index';\nimport { usePrevious } from './use-previous';\n\nexport function usePageViewAnalytics(pathname: string) {\n const prevPathname = usePrevious(pathname);\n const session = useRef({ start: performance.now(), total: 0, isActive: true });\n\n useEffect(() => {\n const handler = () => {\n if (document.hidden) {\n session.current.total += (performance.now() - session.current.start) / 1000;\n session.current.isActive = false;\n } else {\n session.current.start = performance.now();\n session.current.isActive = true;\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, []);\n\n // send first_visit event when the page is loaded\n useEffect(() => {\n const key = 'first_visit_time';\n if (config.storage.getItem(key)) return;\n const properties = {\n page_path: pathname,\n page_title: document.title,\n page_referrer: document.referrer,\n page_location: window.location.href,\n };\n track('first_visit', properties, { enableThirdPartyTracking: false });\n config.storage.setItem(key, new Date().toISOString());\n }, []);\n\n useEffect(() => {\n if (!prevPathname) {\n session.current = { start: performance.now(), total: 0, isActive: true };\n }\n\n let duration = session.current.total;\n if (session.current.isActive) {\n duration += (performance.now() - session.current.start) / 1000;\n }\n\n const properties = {\n page_path: pathname,\n page_title: document.title,\n page_referrer: document.referrer,\n page_location: window.location.href,\n previous_page_path: prevPathname ?? undefined,\n previous_page_path_duration: prevPathname ? Number(duration.toFixed(2)) : undefined,\n };\n\n track('page_view', properties, { enableThirdPartyTracking: false });\n\n // reset session\n session.current = { start: performance.now(), total: 0, isActive: true };\n }, [pathname]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAkC;AAClC,mBAAuB;AACvB,mBAAsB;AACtB,0BAA4B;AAErB,SAAS,qBAAqB,UAAkB;AACrD,QAAM,mBAAe,iCAAY,QAAQ;AACzC,QAAM,cAAU,qBAAO,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAE7E,8BAAU,MAAM;AACd,UAAM,UAAU,MAAM;AACpB,UAAI,SAAS,QAAQ;AACnB,gBAAQ,QAAQ,UAAU,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AACvE,gBAAQ,QAAQ,WAAW;AAAA,MAC7B,OAAO;AACL,gBAAQ,QAAQ,QAAQ,YAAY,IAAI;AACxC,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,OAAO;AACrD,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,OAAO;AAAA,EACvE,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,UAAM,MAAM;AACZ,QAAI,oBAAO,QAAQ,QAAQ,GAAG,EAAG;AACjC,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,YAAY,SAAS;AAAA,MACrB,eAAe,SAAS;AAAA,MACxB,eAAe,OAAO,SAAS;AAAA,IACjC;AACA,4BAAM,eAAe,YAAY,EAAE,0BAA0B,MAAM,CAAC;AACpE,wBAAO,QAAQ,QAAQ,MAAK,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACtD,GAAG,CAAC,CAAC;AAEL,8BAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,cAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,IACzE;AAEA,QAAI,WAAW,QAAQ,QAAQ;AAC/B,QAAI,QAAQ,QAAQ,UAAU;AAC5B,mBAAa,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AAAA,IAC5D;AAEA,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,YAAY,SAAS;AAAA,MACrB,eAAe,SAAS;AAAA,MACxB,eAAe,OAAO,SAAS;AAAA,MAC/B,oBAAoB,gBAAgB;AAAA,MACpC,6BAA6B,eAAe,OAAO,SAAS,QAAQ,CAAC,CAAC,IAAI;AAAA,IAC5E;AAEA,4BAAM,aAAa,YAAY,EAAE,0BAA0B,MAAM,CAAC;AAGlE,YAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,EACzE,GAAG,CAAC,QAAQ,CAAC;AACf;","names":[]}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// src/hooks/use-page-view-analytics.ts
|
|
2
|
-
import { useEffect, useRef } from "react";
|
|
3
|
-
import { config } from "../setup/index.mjs";
|
|
4
|
-
import { track } from "../track/index.mjs";
|
|
5
|
-
import { usePrevious } from "./use-previous.mjs";
|
|
6
|
-
function usePageViewAnalytics(pathname) {
|
|
7
|
-
const prevPathname = usePrevious(pathname);
|
|
8
|
-
const session = useRef({ start: performance.now(), total: 0, isActive: true });
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
const handler = () => {
|
|
11
|
-
if (document.hidden) {
|
|
12
|
-
session.current.total += (performance.now() - session.current.start) / 1e3;
|
|
13
|
-
session.current.isActive = false;
|
|
14
|
-
} else {
|
|
15
|
-
session.current.start = performance.now();
|
|
16
|
-
session.current.isActive = true;
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
document.addEventListener("visibilitychange", handler);
|
|
20
|
-
return () => document.removeEventListener("visibilitychange", handler);
|
|
21
|
-
}, []);
|
|
22
|
-
useEffect(() => {
|
|
23
|
-
const key = "first_visit_time";
|
|
24
|
-
if (config.storage.getItem(key)) return;
|
|
25
|
-
const properties = {
|
|
26
|
-
page_path: pathname,
|
|
27
|
-
page_title: document.title,
|
|
28
|
-
page_referrer: document.referrer,
|
|
29
|
-
page_location: window.location.href
|
|
30
|
-
};
|
|
31
|
-
track("first_visit", properties, { enableThirdPartyTracking: false });
|
|
32
|
-
config.storage.setItem(key, (/* @__PURE__ */ new Date()).toISOString());
|
|
33
|
-
}, []);
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
if (!prevPathname) {
|
|
36
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
37
|
-
}
|
|
38
|
-
let duration = session.current.total;
|
|
39
|
-
if (session.current.isActive) {
|
|
40
|
-
duration += (performance.now() - session.current.start) / 1e3;
|
|
41
|
-
}
|
|
42
|
-
const properties = {
|
|
43
|
-
page_path: pathname,
|
|
44
|
-
page_title: document.title,
|
|
45
|
-
page_referrer: document.referrer,
|
|
46
|
-
page_location: window.location.href,
|
|
47
|
-
previous_page_path: prevPathname ?? void 0,
|
|
48
|
-
previous_page_path_duration: prevPathname ? Number(duration.toFixed(2)) : void 0
|
|
49
|
-
};
|
|
50
|
-
track("page_view", properties, { enableThirdPartyTracking: false });
|
|
51
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
52
|
-
}, [pathname]);
|
|
53
|
-
}
|
|
54
|
-
export {
|
|
55
|
-
usePageViewAnalytics
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=use-page-view-analytics.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-page-view-analytics.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { config } from '../setup/index';\nimport { track } from '../track/index';\nimport { usePrevious } from './use-previous';\n\nexport function usePageViewAnalytics(pathname: string) {\n const prevPathname = usePrevious(pathname);\n const session = useRef({ start: performance.now(), total: 0, isActive: true });\n\n useEffect(() => {\n const handler = () => {\n if (document.hidden) {\n session.current.total += (performance.now() - session.current.start) / 1000;\n session.current.isActive = false;\n } else {\n session.current.start = performance.now();\n session.current.isActive = true;\n }\n };\n document.addEventListener('visibilitychange', handler);\n return () => document.removeEventListener('visibilitychange', handler);\n }, []);\n\n // send first_visit event when the page is loaded\n useEffect(() => {\n const key = 'first_visit_time';\n if (config.storage.getItem(key)) return;\n const properties = {\n page_path: pathname,\n page_title: document.title,\n page_referrer: document.referrer,\n page_location: window.location.href,\n };\n track('first_visit', properties, { enableThirdPartyTracking: false });\n config.storage.setItem(key, new Date().toISOString());\n }, []);\n\n useEffect(() => {\n if (!prevPathname) {\n session.current = { start: performance.now(), total: 0, isActive: true };\n }\n\n let duration = session.current.total;\n if (session.current.isActive) {\n duration += (performance.now() - session.current.start) / 1000;\n }\n\n const properties = {\n page_path: pathname,\n page_title: document.title,\n page_referrer: document.referrer,\n page_location: window.location.href,\n previous_page_path: prevPathname ?? undefined,\n previous_page_path_duration: prevPathname ? Number(duration.toFixed(2)) : undefined,\n };\n\n track('page_view', properties, { enableThirdPartyTracking: false });\n\n // reset session\n session.current = { start: performance.now(), total: 0, isActive: true };\n }, [pathname]);\n}\n"],"mappings":";AAAA,SAAS,WAAW,cAAc;AAClC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAErB,SAAS,qBAAqB,UAAkB;AACrD,QAAM,eAAe,YAAY,QAAQ;AACzC,QAAM,UAAU,OAAO,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAE7E,YAAU,MAAM;AACd,UAAM,UAAU,MAAM;AACpB,UAAI,SAAS,QAAQ;AACnB,gBAAQ,QAAQ,UAAU,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AACvE,gBAAQ,QAAQ,WAAW;AAAA,MAC7B,OAAO;AACL,gBAAQ,QAAQ,QAAQ,YAAY,IAAI;AACxC,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,OAAO;AACrD,WAAO,MAAM,SAAS,oBAAoB,oBAAoB,OAAO;AAAA,EACvE,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,UAAM,MAAM;AACZ,QAAI,OAAO,QAAQ,QAAQ,GAAG,EAAG;AACjC,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,YAAY,SAAS;AAAA,MACrB,eAAe,SAAS;AAAA,MACxB,eAAe,OAAO,SAAS;AAAA,IACjC;AACA,UAAM,eAAe,YAAY,EAAE,0BAA0B,MAAM,CAAC;AACpE,WAAO,QAAQ,QAAQ,MAAK,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACtD,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,cAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,IACzE;AAEA,QAAI,WAAW,QAAQ,QAAQ;AAC/B,QAAI,QAAQ,QAAQ,UAAU;AAC5B,mBAAa,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AAAA,IAC5D;AAEA,UAAM,aAAa;AAAA,MACjB,WAAW;AAAA,MACX,YAAY,SAAS;AAAA,MACrB,eAAe,SAAS;AAAA,MACxB,eAAe,OAAO,SAAS;AAAA,MAC/B,oBAAoB,gBAAgB;AAAA,MACpC,6BAA6B,eAAe,OAAO,SAAS,QAAQ,CAAC,CAAC,IAAI;AAAA,IAC5E;AAEA,UAAM,aAAa,YAAY,EAAE,0BAA0B,MAAM,CAAC;AAGlE,YAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,EACzE,GAAG,CAAC,QAAQ,CAAC;AACf;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-screen-view-analytics.ts"],"sourcesContent":["import { usePathname } from 'expo-router';\nimport { useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { config } from '../setup/index';\nimport { track } from '../track/index';\nimport { usePrevious } from './use-previous';\n\nexport function useScreenViewAnalytics() {\n const pathname = usePathname();\n const prevPathname = usePrevious(pathname);\n const session = useRef({ start: performance.now(), total: 0, isActive: true });\n\n useEffect(() => {\n const subscription = AppState.addEventListener('change', (state) => {\n // when returning to the foreground from the background\n if (state === 'active' && !session.current.isActive) {\n session.current.start = performance.now();\n session.current.isActive = true;\n }\n // when entering the background\n else if (state !== 'active' && session.current.isActive) {\n session.current.total += (performance.now() - session.current.start) / 1000;\n session.current.isActive = false;\n }\n });\n\n return () => subscription.remove();\n }, []);\n\n // send first_visit event when the page is loaded\n useEffect(() => {\n const key = 'first_open_time';\n if (config.storage.getItem(key)) return;\n const properties = { screen_name: pathname, screen_class: pathname };\n track('first_open', properties, { enableThirdPartyTracking: false });\n config.storage.setItem(key, new Date().toISOString());\n }, []);\n\n // when the screen is switched, the duration of the previous screen is recorded\n useEffect(() => {\n if (!prevPathname) {\n session.current = { start: performance.now(), total: 0, isActive: true };\n }\n\n let duration = session.current.total;\n if (session.current.isActive) {\n duration += (performance.now() - session.current.start) / 1000;\n }\n\n track('screen_view', {\n screen_name: pathname,\n screen_class: pathname,\n previous_screen_class: prevPathname ?? undefined,\n previous_screen_class_duration: prevPathname ? Number(duration.toFixed(2)) : undefined,\n });\n\n // reset session\n session.current = { start: performance.now(), total: 0, isActive: true };\n }, [pathname]);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA4B;AAC5B,mBAAkC;AAClC,0BAAyB;AACzB,mBAAuB;AACvB,mBAAsB;AACtB,0BAA4B;AAErB,SAAS,yBAAyB;AACvC,QAAM,eAAW,gCAAY;AAC7B,QAAM,mBAAe,iCAAY,QAAQ;AACzC,QAAM,cAAU,qBAAO,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAE7E,8BAAU,MAAM;AACd,UAAM,eAAe,6BAAS,iBAAiB,UAAU,CAAC,UAAU;AAElE,UAAI,UAAU,YAAY,CAAC,QAAQ,QAAQ,UAAU;AACnD,gBAAQ,QAAQ,QAAQ,YAAY,IAAI;AACxC,gBAAQ,QAAQ,WAAW;AAAA,MAC7B,WAES,UAAU,YAAY,QAAQ,QAAQ,UAAU;AACvD,gBAAQ,QAAQ,UAAU,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AACvE,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,UAAM,MAAM;AACZ,QAAI,oBAAO,QAAQ,QAAQ,GAAG,EAAG;AACjC,UAAM,aAAa,EAAE,aAAa,UAAU,cAAc,SAAS;AACnE,4BAAM,cAAc,YAAY,EAAE,0BAA0B,MAAM,CAAC;AACnE,wBAAO,QAAQ,QAAQ,MAAK,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACtD,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,cAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,IACzE;AAEA,QAAI,WAAW,QAAQ,QAAQ;AAC/B,QAAI,QAAQ,QAAQ,UAAU;AAC5B,mBAAa,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AAAA,IAC5D;AAEA,4BAAM,eAAe;AAAA,MACnB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,uBAAuB,gBAAgB;AAAA,MACvC,gCAAgC,eAAe,OAAO,SAAS,QAAQ,CAAC,CAAC,IAAI;AAAA,IAC/E,CAAC;AAGD,YAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,EACzE,GAAG,CAAC,QAAQ,CAAC;AACf;","names":[]}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// src/hooks/use-screen-view-analytics.ts
|
|
2
|
-
import { usePathname } from "expo-router";
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
4
|
-
import { AppState } from "react-native";
|
|
5
|
-
import { config } from "../setup/index.mjs";
|
|
6
|
-
import { track } from "../track/index.mjs";
|
|
7
|
-
import { usePrevious } from "./use-previous.mjs";
|
|
8
|
-
function useScreenViewAnalytics() {
|
|
9
|
-
const pathname = usePathname();
|
|
10
|
-
const prevPathname = usePrevious(pathname);
|
|
11
|
-
const session = useRef({ start: performance.now(), total: 0, isActive: true });
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const subscription = AppState.addEventListener("change", (state) => {
|
|
14
|
-
if (state === "active" && !session.current.isActive) {
|
|
15
|
-
session.current.start = performance.now();
|
|
16
|
-
session.current.isActive = true;
|
|
17
|
-
} else if (state !== "active" && session.current.isActive) {
|
|
18
|
-
session.current.total += (performance.now() - session.current.start) / 1e3;
|
|
19
|
-
session.current.isActive = false;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
return () => subscription.remove();
|
|
23
|
-
}, []);
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const key = "first_open_time";
|
|
26
|
-
if (config.storage.getItem(key)) return;
|
|
27
|
-
const properties = { screen_name: pathname, screen_class: pathname };
|
|
28
|
-
track("first_open", properties, { enableThirdPartyTracking: false });
|
|
29
|
-
config.storage.setItem(key, (/* @__PURE__ */ new Date()).toISOString());
|
|
30
|
-
}, []);
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
if (!prevPathname) {
|
|
33
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
34
|
-
}
|
|
35
|
-
let duration = session.current.total;
|
|
36
|
-
if (session.current.isActive) {
|
|
37
|
-
duration += (performance.now() - session.current.start) / 1e3;
|
|
38
|
-
}
|
|
39
|
-
track("screen_view", {
|
|
40
|
-
screen_name: pathname,
|
|
41
|
-
screen_class: pathname,
|
|
42
|
-
previous_screen_class: prevPathname ?? void 0,
|
|
43
|
-
previous_screen_class_duration: prevPathname ? Number(duration.toFixed(2)) : void 0
|
|
44
|
-
});
|
|
45
|
-
session.current = { start: performance.now(), total: 0, isActive: true };
|
|
46
|
-
}, [pathname]);
|
|
47
|
-
}
|
|
48
|
-
export {
|
|
49
|
-
useScreenViewAnalytics
|
|
50
|
-
};
|
|
51
|
-
//# sourceMappingURL=use-screen-view-analytics.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-screen-view-analytics.ts"],"sourcesContent":["import { usePathname } from 'expo-router';\nimport { useEffect, useRef } from 'react';\nimport { AppState } from 'react-native';\nimport { config } from '../setup/index';\nimport { track } from '../track/index';\nimport { usePrevious } from './use-previous';\n\nexport function useScreenViewAnalytics() {\n const pathname = usePathname();\n const prevPathname = usePrevious(pathname);\n const session = useRef({ start: performance.now(), total: 0, isActive: true });\n\n useEffect(() => {\n const subscription = AppState.addEventListener('change', (state) => {\n // when returning to the foreground from the background\n if (state === 'active' && !session.current.isActive) {\n session.current.start = performance.now();\n session.current.isActive = true;\n }\n // when entering the background\n else if (state !== 'active' && session.current.isActive) {\n session.current.total += (performance.now() - session.current.start) / 1000;\n session.current.isActive = false;\n }\n });\n\n return () => subscription.remove();\n }, []);\n\n // send first_visit event when the page is loaded\n useEffect(() => {\n const key = 'first_open_time';\n if (config.storage.getItem(key)) return;\n const properties = { screen_name: pathname, screen_class: pathname };\n track('first_open', properties, { enableThirdPartyTracking: false });\n config.storage.setItem(key, new Date().toISOString());\n }, []);\n\n // when the screen is switched, the duration of the previous screen is recorded\n useEffect(() => {\n if (!prevPathname) {\n session.current = { start: performance.now(), total: 0, isActive: true };\n }\n\n let duration = session.current.total;\n if (session.current.isActive) {\n duration += (performance.now() - session.current.start) / 1000;\n }\n\n track('screen_view', {\n screen_name: pathname,\n screen_class: pathname,\n previous_screen_class: prevPathname ?? undefined,\n previous_screen_class_duration: prevPathname ? Number(duration.toFixed(2)) : undefined,\n });\n\n // reset session\n session.current = { start: performance.now(), total: 0, isActive: true };\n }, [pathname]);\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAC5B,SAAS,WAAW,cAAc;AAClC,SAAS,gBAAgB;AACzB,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,mBAAmB;AAErB,SAAS,yBAAyB;AACvC,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,YAAY,QAAQ;AACzC,QAAM,UAAU,OAAO,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK,CAAC;AAE7E,YAAU,MAAM;AACd,UAAM,eAAe,SAAS,iBAAiB,UAAU,CAAC,UAAU;AAElE,UAAI,UAAU,YAAY,CAAC,QAAQ,QAAQ,UAAU;AACnD,gBAAQ,QAAQ,QAAQ,YAAY,IAAI;AACxC,gBAAQ,QAAQ,WAAW;AAAA,MAC7B,WAES,UAAU,YAAY,QAAQ,QAAQ,UAAU;AACvD,gBAAQ,QAAQ,UAAU,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AACvE,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,UAAM,MAAM;AACZ,QAAI,OAAO,QAAQ,QAAQ,GAAG,EAAG;AACjC,UAAM,aAAa,EAAE,aAAa,UAAU,cAAc,SAAS;AACnE,UAAM,cAAc,YAAY,EAAE,0BAA0B,MAAM,CAAC;AACnE,WAAO,QAAQ,QAAQ,MAAK,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,EACtD,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,cAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,IACzE;AAEA,QAAI,WAAW,QAAQ,QAAQ;AAC/B,QAAI,QAAQ,QAAQ,UAAU;AAC5B,mBAAa,YAAY,IAAI,IAAI,QAAQ,QAAQ,SAAS;AAAA,IAC5D;AAEA,UAAM,eAAe;AAAA,MACnB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,uBAAuB,gBAAgB;AAAA,MACvC,gCAAgC,eAAe,OAAO,SAAS,QAAQ,CAAC,CAAC,IAAI;AAAA,IAC/E,CAAC;AAGD,YAAQ,UAAU,EAAE,OAAO,YAAY,IAAI,GAAG,OAAO,GAAG,UAAU,KAAK;AAAA,EACzE,GAAG,CAAC,QAAQ,CAAC;AACf;","names":[]}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/hooks/use-web-session-analytics.ts
|
|
21
|
-
var use_web_session_analytics_exports = {};
|
|
22
|
-
__export(use_web_session_analytics_exports, {
|
|
23
|
-
useWebSessionAnalytics: () => useWebSessionAnalytics
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(use_web_session_analytics_exports);
|
|
26
|
-
var import_utils = require("@shware/utils");
|
|
27
|
-
var import_react = require("react");
|
|
28
|
-
var import_session = require("../setup/session.cjs");
|
|
29
|
-
var import_track = require("../track/index.cjs");
|
|
30
|
-
function useWebSessionAnalytics(pathname) {
|
|
31
|
-
const isActive = (0, import_react.useRef)(true);
|
|
32
|
-
const isFocused = (0, import_react.useRef)(true);
|
|
33
|
-
const isVisible = (0, import_react.useRef)(true);
|
|
34
|
-
const startTime = (0, import_react.useRef)(Date.now());
|
|
35
|
-
const accumulatedTime = (0, import_react.useRef)(0);
|
|
36
|
-
const hasSendScroll = (0, import_react.useRef)(false);
|
|
37
|
-
const updateAccumulator = (0, import_react.useCallback)(() => {
|
|
38
|
-
const now = Date.now();
|
|
39
|
-
if (isFocused.current && isVisible.current && isActive.current) {
|
|
40
|
-
const delta = now - startTime.current;
|
|
41
|
-
if (delta > 0 && delta < import_session.SESSION_TIMEOUT) {
|
|
42
|
-
accumulatedTime.current += delta;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
startTime.current = now;
|
|
46
|
-
}, []);
|
|
47
|
-
const sendUserEngagement = (0, import_react.useCallback)(() => {
|
|
48
|
-
updateAccumulator();
|
|
49
|
-
const engagement_time_msec = accumulatedTime.current;
|
|
50
|
-
accumulatedTime.current = 0;
|
|
51
|
-
if (engagement_time_msec <= 0) return;
|
|
52
|
-
(0, import_track.sendBeacon)("user_engagement", { engagement_time_msec });
|
|
53
|
-
}, [updateAccumulator]);
|
|
54
|
-
const sendScroll = (0, import_react.useCallback)(() => {
|
|
55
|
-
updateAccumulator();
|
|
56
|
-
const engagement_time_msec = accumulatedTime.current;
|
|
57
|
-
accumulatedTime.current = 0;
|
|
58
|
-
if (engagement_time_msec <= 0) return;
|
|
59
|
-
(0, import_track.track)("scroll", { engagement_time_msec }, { enableThirdPartyTracking: false });
|
|
60
|
-
}, [updateAccumulator]);
|
|
61
|
-
(0, import_react.useEffect)(() => {
|
|
62
|
-
hasSendScroll.current = false;
|
|
63
|
-
}, [pathname]);
|
|
64
|
-
(0, import_react.useEffect)(() => {
|
|
65
|
-
isFocused.current = typeof document !== "undefined" && document.hasFocus();
|
|
66
|
-
isVisible.current = typeof document !== "undefined" && document.visibilityState === "visible";
|
|
67
|
-
startTime.current = Date.now();
|
|
68
|
-
(0, import_track.track)("session_start", void 0, { enableThirdPartyTracking: false });
|
|
69
|
-
const onFocus = () => {
|
|
70
|
-
updateAccumulator();
|
|
71
|
-
isFocused.current = true;
|
|
72
|
-
};
|
|
73
|
-
const onBlur = () => {
|
|
74
|
-
updateAccumulator();
|
|
75
|
-
isFocused.current = false;
|
|
76
|
-
};
|
|
77
|
-
const onPageShow = () => {
|
|
78
|
-
updateAccumulator();
|
|
79
|
-
isActive.current = true;
|
|
80
|
-
};
|
|
81
|
-
const onPageHide = () => {
|
|
82
|
-
updateAccumulator();
|
|
83
|
-
isActive.current = false;
|
|
84
|
-
sendUserEngagement();
|
|
85
|
-
};
|
|
86
|
-
const onVisibilityChange = () => {
|
|
87
|
-
updateAccumulator();
|
|
88
|
-
if (document.visibilityState === "visible") {
|
|
89
|
-
isVisible.current = true;
|
|
90
|
-
} else {
|
|
91
|
-
isVisible.current = false;
|
|
92
|
-
sendUserEngagement();
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
const onScroll = (0, import_utils.throttle)(() => {
|
|
96
|
-
updateAccumulator();
|
|
97
|
-
if (hasSendScroll.current) return;
|
|
98
|
-
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
99
|
-
const windowHeight = window.innerHeight;
|
|
100
|
-
const docHeight = document.documentElement.scrollHeight;
|
|
101
|
-
if (docHeight === 0) return;
|
|
102
|
-
const scrollPercent = (scrollTop + windowHeight) / docHeight;
|
|
103
|
-
if (scrollPercent < 0.9) return;
|
|
104
|
-
hasSendScroll.current = true;
|
|
105
|
-
sendScroll();
|
|
106
|
-
}, 500);
|
|
107
|
-
const checkpointEvents = ["mousedown", "keydown", "touchstart"];
|
|
108
|
-
const checkpoint = (0, import_utils.throttle)(updateAccumulator, 1e3);
|
|
109
|
-
window.addEventListener("focus", onFocus, { passive: true });
|
|
110
|
-
window.addEventListener("blur", onBlur, { passive: true });
|
|
111
|
-
window.addEventListener("pageshow", onPageShow, { passive: true });
|
|
112
|
-
window.addEventListener("pagehide", onPageHide, { passive: true });
|
|
113
|
-
window.addEventListener("scroll", onScroll, { passive: true });
|
|
114
|
-
document.addEventListener("visibilitychange", onVisibilityChange, { passive: true });
|
|
115
|
-
checkpointEvents.forEach((event) => {
|
|
116
|
-
window.addEventListener(event, checkpoint, { passive: true, capture: true });
|
|
117
|
-
});
|
|
118
|
-
return () => {
|
|
119
|
-
window.removeEventListener("focus", onFocus);
|
|
120
|
-
window.removeEventListener("blur", onBlur);
|
|
121
|
-
window.removeEventListener("pageshow", onPageShow);
|
|
122
|
-
window.removeEventListener("pagehide", onPageHide);
|
|
123
|
-
window.removeEventListener("scroll", onScroll);
|
|
124
|
-
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
125
|
-
checkpointEvents.forEach((event) => {
|
|
126
|
-
window.removeEventListener(event, checkpoint);
|
|
127
|
-
});
|
|
128
|
-
onScroll.cancel();
|
|
129
|
-
checkpoint.cancel();
|
|
130
|
-
};
|
|
131
|
-
}, []);
|
|
132
|
-
}
|
|
133
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
134
|
-
0 && (module.exports = {
|
|
135
|
-
useWebSessionAnalytics
|
|
136
|
-
});
|
|
137
|
-
//# sourceMappingURL=use-web-session-analytics.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-web-session-analytics.ts"],"sourcesContent":["/**\n * reference:\n * - Discover how long someone spends engaged on your website or app in Google Analytics](https://support.google.com/analytics/answer/11109416?hl=en)\n */\nimport { throttle } from '@shware/utils';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { SESSION_TIMEOUT } from '../setup/session';\nimport { sendBeacon, track } from '../track/index';\n\n/**\n * 1. send session_start event when the page is loaded\n * 2. send scroll event when the user scrolls more than 90% of the page\n * 3. send user_engagement event when the page is hidden or the user is not focused\n */\nexport function useWebSessionAnalytics(pathname: string) {\n const isActive = useRef(true);\n const isFocused = useRef(true);\n const isVisible = useRef(true);\n\n const startTime = useRef(Date.now());\n const accumulatedTime = useRef(0);\n\n const hasSendScroll = useRef(false);\n\n const updateAccumulator = useCallback(() => {\n const now = Date.now();\n if (isFocused.current && isVisible.current && isActive.current) {\n const delta = now - startTime.current;\n if (delta > 0 && delta < SESSION_TIMEOUT) {\n accumulatedTime.current += delta;\n }\n }\n startTime.current = now;\n }, []);\n\n const sendUserEngagement = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n sendBeacon('user_engagement', { engagement_time_msec });\n }, [updateAccumulator]);\n\n const sendScroll = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n track('scroll', { engagement_time_msec }, { enableThirdPartyTracking: false });\n }, [updateAccumulator]);\n\n // reset scroll state when the pathname changes, so we can send scroll when the user navigates to\n // a new page\n useEffect(() => {\n hasSendScroll.current = false;\n }, [pathname]);\n\n useEffect(() => {\n isFocused.current = typeof document !== 'undefined' && document.hasFocus();\n isVisible.current = typeof document !== 'undefined' && document.visibilityState === 'visible';\n startTime.current = Date.now();\n\n track('session_start', undefined, { enableThirdPartyTracking: false });\n\n const onFocus = () => {\n updateAccumulator();\n isFocused.current = true;\n };\n\n const onBlur = () => {\n updateAccumulator();\n isFocused.current = false;\n };\n\n const onPageShow = () => {\n updateAccumulator();\n isActive.current = true;\n };\n\n const onPageHide = () => {\n updateAccumulator();\n isActive.current = false;\n sendUserEngagement();\n };\n\n const onVisibilityChange = () => {\n updateAccumulator();\n if (document.visibilityState === 'visible') {\n isVisible.current = true;\n } else {\n isVisible.current = false;\n sendUserEngagement();\n }\n };\n\n const onScroll = throttle(() => {\n updateAccumulator();\n if (hasSendScroll.current) return;\n\n // only send scroll when the user has scrolled more than 90% of the page\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight;\n if (docHeight === 0) return;\n const scrollPercent = (scrollTop + windowHeight) / docHeight;\n if (scrollPercent < 0.9) return;\n hasSendScroll.current = true;\n\n sendScroll();\n }, 500);\n\n const checkpointEvents = ['mousedown', 'keydown', 'touchstart'];\n const checkpoint = throttle(updateAccumulator, 1000);\n\n window.addEventListener('focus', onFocus, { passive: true });\n window.addEventListener('blur', onBlur, { passive: true });\n window.addEventListener('pageshow', onPageShow, { passive: true });\n window.addEventListener('pagehide', onPageHide, { passive: true });\n window.addEventListener('scroll', onScroll, { passive: true });\n document.addEventListener('visibilitychange', onVisibilityChange, { passive: true });\n\n // save checkpoint\n checkpointEvents.forEach((event) => {\n window.addEventListener(event, checkpoint, { passive: true, capture: true });\n });\n\n return () => {\n window.removeEventListener('focus', onFocus);\n window.removeEventListener('blur', onBlur);\n window.removeEventListener('pageshow', onPageShow);\n window.removeEventListener('pagehide', onPageHide);\n window.removeEventListener('scroll', onScroll);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n\n checkpointEvents.forEach((event) => {\n window.removeEventListener(event, checkpoint);\n });\n\n onScroll.cancel();\n checkpoint.cancel();\n };\n }, []);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// src/hooks/use-web-session-analytics.ts
|
|
2
|
-
import { throttle } from "@shware/utils";
|
|
3
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
4
|
-
import { SESSION_TIMEOUT } from "../setup/session.mjs";
|
|
5
|
-
import { sendBeacon, track } from "../track/index.mjs";
|
|
6
|
-
function useWebSessionAnalytics(pathname) {
|
|
7
|
-
const isActive = useRef(true);
|
|
8
|
-
const isFocused = useRef(true);
|
|
9
|
-
const isVisible = useRef(true);
|
|
10
|
-
const startTime = useRef(Date.now());
|
|
11
|
-
const accumulatedTime = useRef(0);
|
|
12
|
-
const hasSendScroll = useRef(false);
|
|
13
|
-
const updateAccumulator = useCallback(() => {
|
|
14
|
-
const now = Date.now();
|
|
15
|
-
if (isFocused.current && isVisible.current && isActive.current) {
|
|
16
|
-
const delta = now - startTime.current;
|
|
17
|
-
if (delta > 0 && delta < SESSION_TIMEOUT) {
|
|
18
|
-
accumulatedTime.current += delta;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
startTime.current = now;
|
|
22
|
-
}, []);
|
|
23
|
-
const sendUserEngagement = useCallback(() => {
|
|
24
|
-
updateAccumulator();
|
|
25
|
-
const engagement_time_msec = accumulatedTime.current;
|
|
26
|
-
accumulatedTime.current = 0;
|
|
27
|
-
if (engagement_time_msec <= 0) return;
|
|
28
|
-
sendBeacon("user_engagement", { engagement_time_msec });
|
|
29
|
-
}, [updateAccumulator]);
|
|
30
|
-
const sendScroll = useCallback(() => {
|
|
31
|
-
updateAccumulator();
|
|
32
|
-
const engagement_time_msec = accumulatedTime.current;
|
|
33
|
-
accumulatedTime.current = 0;
|
|
34
|
-
if (engagement_time_msec <= 0) return;
|
|
35
|
-
track("scroll", { engagement_time_msec }, { enableThirdPartyTracking: false });
|
|
36
|
-
}, [updateAccumulator]);
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
hasSendScroll.current = false;
|
|
39
|
-
}, [pathname]);
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
isFocused.current = typeof document !== "undefined" && document.hasFocus();
|
|
42
|
-
isVisible.current = typeof document !== "undefined" && document.visibilityState === "visible";
|
|
43
|
-
startTime.current = Date.now();
|
|
44
|
-
track("session_start", void 0, { enableThirdPartyTracking: false });
|
|
45
|
-
const onFocus = () => {
|
|
46
|
-
updateAccumulator();
|
|
47
|
-
isFocused.current = true;
|
|
48
|
-
};
|
|
49
|
-
const onBlur = () => {
|
|
50
|
-
updateAccumulator();
|
|
51
|
-
isFocused.current = false;
|
|
52
|
-
};
|
|
53
|
-
const onPageShow = () => {
|
|
54
|
-
updateAccumulator();
|
|
55
|
-
isActive.current = true;
|
|
56
|
-
};
|
|
57
|
-
const onPageHide = () => {
|
|
58
|
-
updateAccumulator();
|
|
59
|
-
isActive.current = false;
|
|
60
|
-
sendUserEngagement();
|
|
61
|
-
};
|
|
62
|
-
const onVisibilityChange = () => {
|
|
63
|
-
updateAccumulator();
|
|
64
|
-
if (document.visibilityState === "visible") {
|
|
65
|
-
isVisible.current = true;
|
|
66
|
-
} else {
|
|
67
|
-
isVisible.current = false;
|
|
68
|
-
sendUserEngagement();
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
const onScroll = throttle(() => {
|
|
72
|
-
updateAccumulator();
|
|
73
|
-
if (hasSendScroll.current) return;
|
|
74
|
-
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
75
|
-
const windowHeight = window.innerHeight;
|
|
76
|
-
const docHeight = document.documentElement.scrollHeight;
|
|
77
|
-
if (docHeight === 0) return;
|
|
78
|
-
const scrollPercent = (scrollTop + windowHeight) / docHeight;
|
|
79
|
-
if (scrollPercent < 0.9) return;
|
|
80
|
-
hasSendScroll.current = true;
|
|
81
|
-
sendScroll();
|
|
82
|
-
}, 500);
|
|
83
|
-
const checkpointEvents = ["mousedown", "keydown", "touchstart"];
|
|
84
|
-
const checkpoint = throttle(updateAccumulator, 1e3);
|
|
85
|
-
window.addEventListener("focus", onFocus, { passive: true });
|
|
86
|
-
window.addEventListener("blur", onBlur, { passive: true });
|
|
87
|
-
window.addEventListener("pageshow", onPageShow, { passive: true });
|
|
88
|
-
window.addEventListener("pagehide", onPageHide, { passive: true });
|
|
89
|
-
window.addEventListener("scroll", onScroll, { passive: true });
|
|
90
|
-
document.addEventListener("visibilitychange", onVisibilityChange, { passive: true });
|
|
91
|
-
checkpointEvents.forEach((event) => {
|
|
92
|
-
window.addEventListener(event, checkpoint, { passive: true, capture: true });
|
|
93
|
-
});
|
|
94
|
-
return () => {
|
|
95
|
-
window.removeEventListener("focus", onFocus);
|
|
96
|
-
window.removeEventListener("blur", onBlur);
|
|
97
|
-
window.removeEventListener("pageshow", onPageShow);
|
|
98
|
-
window.removeEventListener("pagehide", onPageHide);
|
|
99
|
-
window.removeEventListener("scroll", onScroll);
|
|
100
|
-
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
101
|
-
checkpointEvents.forEach((event) => {
|
|
102
|
-
window.removeEventListener(event, checkpoint);
|
|
103
|
-
});
|
|
104
|
-
onScroll.cancel();
|
|
105
|
-
checkpoint.cancel();
|
|
106
|
-
};
|
|
107
|
-
}, []);
|
|
108
|
-
}
|
|
109
|
-
export {
|
|
110
|
-
useWebSessionAnalytics
|
|
111
|
-
};
|
|
112
|
-
//# sourceMappingURL=use-web-session-analytics.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/use-web-session-analytics.ts"],"sourcesContent":["/**\n * reference:\n * - Discover how long someone spends engaged on your website or app in Google Analytics](https://support.google.com/analytics/answer/11109416?hl=en)\n */\nimport { throttle } from '@shware/utils';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { SESSION_TIMEOUT } from '../setup/session';\nimport { sendBeacon, track } from '../track/index';\n\n/**\n * 1. send session_start event when the page is loaded\n * 2. send scroll event when the user scrolls more than 90% of the page\n * 3. send user_engagement event when the page is hidden or the user is not focused\n */\nexport function useWebSessionAnalytics(pathname: string) {\n const isActive = useRef(true);\n const isFocused = useRef(true);\n const isVisible = useRef(true);\n\n const startTime = useRef(Date.now());\n const accumulatedTime = useRef(0);\n\n const hasSendScroll = useRef(false);\n\n const updateAccumulator = useCallback(() => {\n const now = Date.now();\n if (isFocused.current && isVisible.current && isActive.current) {\n const delta = now - startTime.current;\n if (delta > 0 && delta < SESSION_TIMEOUT) {\n accumulatedTime.current += delta;\n }\n }\n startTime.current = now;\n }, []);\n\n const sendUserEngagement = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n sendBeacon('user_engagement', { engagement_time_msec });\n }, [updateAccumulator]);\n\n const sendScroll = useCallback(() => {\n updateAccumulator();\n const engagement_time_msec = accumulatedTime.current;\n accumulatedTime.current = 0;\n if (engagement_time_msec <= 0) return;\n track('scroll', { engagement_time_msec }, { enableThirdPartyTracking: false });\n }, [updateAccumulator]);\n\n // reset scroll state when the pathname changes, so we can send scroll when the user navigates to\n // a new page\n useEffect(() => {\n hasSendScroll.current = false;\n }, [pathname]);\n\n useEffect(() => {\n isFocused.current = typeof document !== 'undefined' && document.hasFocus();\n isVisible.current = typeof document !== 'undefined' && document.visibilityState === 'visible';\n startTime.current = Date.now();\n\n track('session_start', undefined, { enableThirdPartyTracking: false });\n\n const onFocus = () => {\n updateAccumulator();\n isFocused.current = true;\n };\n\n const onBlur = () => {\n updateAccumulator();\n isFocused.current = false;\n };\n\n const onPageShow = () => {\n updateAccumulator();\n isActive.current = true;\n };\n\n const onPageHide = () => {\n updateAccumulator();\n isActive.current = false;\n sendUserEngagement();\n };\n\n const onVisibilityChange = () => {\n updateAccumulator();\n if (document.visibilityState === 'visible') {\n isVisible.current = true;\n } else {\n isVisible.current = false;\n sendUserEngagement();\n }\n };\n\n const onScroll = throttle(() => {\n updateAccumulator();\n if (hasSendScroll.current) return;\n\n // only send scroll when the user has scrolled more than 90% of the page\n const scrollTop = window.scrollY || document.documentElement.scrollTop;\n const windowHeight = window.innerHeight;\n const docHeight = document.documentElement.scrollHeight;\n if (docHeight === 0) return;\n const scrollPercent = (scrollTop + windowHeight) / docHeight;\n if (scrollPercent < 0.9) return;\n hasSendScroll.current = true;\n\n sendScroll();\n }, 500);\n\n const checkpointEvents = ['mousedown', 'keydown', 'touchstart'];\n const checkpoint = throttle(updateAccumulator, 1000);\n\n window.addEventListener('focus', onFocus, { passive: true });\n window.addEventListener('blur', onBlur, { passive: true });\n window.addEventListener('pageshow', onPageShow, { passive: true });\n window.addEventListener('pagehide', onPageHide, { passive: true });\n window.addEventListener('scroll', onScroll, { passive: true });\n document.addEventListener('visibilitychange', onVisibilityChange, { passive: true });\n\n // save checkpoint\n checkpointEvents.forEach((event) => {\n window.addEventListener(event, checkpoint, { passive: true, capture: true });\n });\n\n return () => {\n window.removeEventListener('focus', onFocus);\n window.removeEventListener('blur', onBlur);\n window.removeEventListener('pageshow', onPageShow);\n window.removeEventListener('pagehide', onPageHide);\n window.removeEventListener('scroll', onScroll);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n\n checkpointEvents.forEach((event) => {\n window.removeEventListener(event, checkpoint);\n });\n\n onScroll.cancel();\n checkpoint.cancel();\n };\n }, []);\n}\n"],"mappings":";AAIA,SAAS,gBAAgB;AACzB,SAAS,aAAa,WAAW,cAAc;AAC/C,SAAS,uBAAuB;AAChC,SAAS,YAAY,aAAa;AAO3B,SAAS,uBAAuB,UAAkB;AACvD,QAAM,WAAW,OAAO,IAAI;AAC5B,QAAM,YAAY,OAAO,IAAI;AAC7B,QAAM,YAAY,OAAO,IAAI;AAE7B,QAAM,YAAY,OAAO,KAAK,IAAI,CAAC;AACnC,QAAM,kBAAkB,OAAO,CAAC;AAEhC,QAAM,gBAAgB,OAAO,KAAK;AAElC,QAAM,oBAAoB,YAAY,MAAM;AAC1C,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,UAAU,WAAW,UAAU,WAAW,SAAS,SAAS;AAC9D,YAAM,QAAQ,MAAM,UAAU;AAC9B,UAAI,QAAQ,KAAK,QAAQ,iBAAiB;AACxC,wBAAgB,WAAW;AAAA,MAC7B;AAAA,IACF;AACA,cAAU,UAAU;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,YAAY,MAAM;AAC3C,sBAAkB;AAClB,UAAM,uBAAuB,gBAAgB;AAC7C,oBAAgB,UAAU;AAC1B,QAAI,wBAAwB,EAAG;AAC/B,eAAW,mBAAmB,EAAE,qBAAqB,CAAC;AAAA,EACxD,GAAG,CAAC,iBAAiB,CAAC;AAEtB,QAAM,aAAa,YAAY,MAAM;AACnC,sBAAkB;AAClB,UAAM,uBAAuB,gBAAgB;AAC7C,oBAAgB,UAAU;AAC1B,QAAI,wBAAwB,EAAG;AAC/B,UAAM,UAAU,EAAE,qBAAqB,GAAG,EAAE,0BAA0B,MAAM,CAAC;AAAA,EAC/E,GAAG,CAAC,iBAAiB,CAAC;AAItB,YAAU,MAAM;AACd,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,YAAU,MAAM;AACd,cAAU,UAAU,OAAO,aAAa,eAAe,SAAS,SAAS;AACzE,cAAU,UAAU,OAAO,aAAa,eAAe,SAAS,oBAAoB;AACpF,cAAU,UAAU,KAAK,IAAI;AAE7B,UAAM,iBAAiB,QAAW,EAAE,0BAA0B,MAAM,CAAC;AAErE,UAAM,UAAU,MAAM;AACpB,wBAAkB;AAClB,gBAAU,UAAU;AAAA,IACtB;AAEA,UAAM,SAAS,MAAM;AACnB,wBAAkB;AAClB,gBAAU,UAAU;AAAA,IACtB;AAEA,UAAM,aAAa,MAAM;AACvB,wBAAkB;AAClB,eAAS,UAAU;AAAA,IACrB;AAEA,UAAM,aAAa,MAAM;AACvB,wBAAkB;AAClB,eAAS,UAAU;AACnB,yBAAmB;AAAA,IACrB;AAEA,UAAM,qBAAqB,MAAM;AAC/B,wBAAkB;AAClB,UAAI,SAAS,oBAAoB,WAAW;AAC1C,kBAAU,UAAU;AAAA,MACtB,OAAO;AACL,kBAAU,UAAU;AACpB,2BAAmB;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,WAAW,SAAS,MAAM;AAC9B,wBAAkB;AAClB,UAAI,cAAc,QAAS;AAG3B,YAAM,YAAY,OAAO,WAAW,SAAS,gBAAgB;AAC7D,YAAM,eAAe,OAAO;AAC5B,YAAM,YAAY,SAAS,gBAAgB;AAC3C,UAAI,cAAc,EAAG;AACrB,YAAM,iBAAiB,YAAY,gBAAgB;AACnD,UAAI,gBAAgB,IAAK;AACzB,oBAAc,UAAU;AAExB,iBAAW;AAAA,IACb,GAAG,GAAG;AAEN,UAAM,mBAAmB,CAAC,aAAa,WAAW,YAAY;AAC9D,UAAM,aAAa,SAAS,mBAAmB,GAAI;AAEnD,WAAO,iBAAiB,SAAS,SAAS,EAAE,SAAS,KAAK,CAAC;AAC3D,WAAO,iBAAiB,QAAQ,QAAQ,EAAE,SAAS,KAAK,CAAC;AACzD,WAAO,iBAAiB,YAAY,YAAY,EAAE,SAAS,KAAK,CAAC;AACjE,WAAO,iBAAiB,YAAY,YAAY,EAAE,SAAS,KAAK,CAAC;AACjE,WAAO,iBAAiB,UAAU,UAAU,EAAE,SAAS,KAAK,CAAC;AAC7D,aAAS,iBAAiB,oBAAoB,oBAAoB,EAAE,SAAS,KAAK,CAAC;AAGnF,qBAAiB,QAAQ,CAAC,UAAU;AAClC,aAAO,iBAAiB,OAAO,YAAY,EAAE,SAAS,MAAM,SAAS,KAAK,CAAC;AAAA,IAC7E,CAAC;AAED,WAAO,MAAM;AACX,aAAO,oBAAoB,SAAS,OAAO;AAC3C,aAAO,oBAAoB,QAAQ,MAAM;AACzC,aAAO,oBAAoB,YAAY,UAAU;AACjD,aAAO,oBAAoB,YAAY,UAAU;AACjD,aAAO,oBAAoB,UAAU,QAAQ;AAC7C,eAAS,oBAAoB,oBAAoB,kBAAkB;AAEnE,uBAAiB,QAAQ,CAAC,UAAU;AAClC,eAAO,oBAAoB,OAAO,UAAU;AAAA,MAC9C,CAAC;AAED,eAAS,OAAO;AAChB,iBAAW,OAAO;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AACP;","names":[]}
|