@grainql/analytics-web 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/dist/activity.d.ts +59 -0
  2. package/dist/activity.d.ts.map +1 -0
  3. package/dist/activity.js +131 -0
  4. package/dist/cjs/activity.d.ts +59 -0
  5. package/dist/cjs/activity.d.ts.map +1 -0
  6. package/dist/cjs/activity.js +131 -0
  7. package/dist/cjs/activity.js.map +1 -0
  8. package/dist/cjs/consent.d.ts +68 -0
  9. package/dist/cjs/consent.d.ts.map +1 -0
  10. package/dist/cjs/consent.js +191 -0
  11. package/dist/cjs/consent.js.map +1 -0
  12. package/dist/cjs/cookies.d.ts +28 -0
  13. package/dist/cjs/cookies.d.ts.map +1 -0
  14. package/dist/cjs/cookies.js +95 -0
  15. package/dist/cjs/cookies.js.map +1 -0
  16. package/dist/cjs/heartbeat.d.ts +42 -0
  17. package/dist/cjs/heartbeat.d.ts.map +1 -0
  18. package/dist/cjs/heartbeat.js +92 -0
  19. package/dist/cjs/heartbeat.js.map +1 -0
  20. package/dist/cjs/index.d.ts +100 -3
  21. package/dist/cjs/index.d.ts.map +1 -1
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/cjs/page-tracking.d.ts +60 -0
  24. package/dist/cjs/page-tracking.d.ts.map +1 -0
  25. package/dist/cjs/page-tracking.js +180 -0
  26. package/dist/cjs/page-tracking.js.map +1 -0
  27. package/dist/cjs/react/components/ConsentBanner.d.ts +16 -0
  28. package/dist/cjs/react/components/ConsentBanner.d.ts.map +1 -0
  29. package/dist/cjs/react/components/ConsentBanner.js +112 -0
  30. package/dist/cjs/react/components/ConsentBanner.js.map +1 -0
  31. package/dist/cjs/react/components/CookieNotice.d.ts +12 -0
  32. package/dist/cjs/react/components/CookieNotice.d.ts.map +1 -0
  33. package/dist/cjs/react/components/CookieNotice.js +62 -0
  34. package/dist/cjs/react/components/CookieNotice.js.map +1 -0
  35. package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  36. package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  37. package/dist/cjs/react/components/PrivacyPreferenceCenter.js +120 -0
  38. package/dist/cjs/react/components/PrivacyPreferenceCenter.js.map +1 -0
  39. package/dist/cjs/react/hooks/useConsent.d.ts +13 -0
  40. package/dist/cjs/react/hooks/useConsent.d.ts.map +1 -0
  41. package/dist/cjs/react/hooks/useConsent.js +84 -0
  42. package/dist/cjs/react/hooks/useConsent.js.map +1 -0
  43. package/dist/cjs/react/hooks/useDataDeletion.d.ts +17 -0
  44. package/dist/cjs/react/hooks/useDataDeletion.d.ts.map +1 -0
  45. package/dist/cjs/react/hooks/useDataDeletion.js +117 -0
  46. package/dist/cjs/react/hooks/useDataDeletion.js.map +1 -0
  47. package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts +15 -0
  48. package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  49. package/dist/cjs/react/hooks/usePrivacyPreferences.js +82 -0
  50. package/dist/cjs/react/hooks/usePrivacyPreferences.js.map +1 -0
  51. package/dist/cjs/react/index.d.ts +11 -0
  52. package/dist/cjs/react/index.d.ts.map +1 -1
  53. package/dist/cjs/react/index.js +15 -1
  54. package/dist/cjs/react/index.js.map +1 -1
  55. package/dist/consent.d.ts +68 -0
  56. package/dist/consent.d.ts.map +1 -0
  57. package/dist/consent.js +191 -0
  58. package/dist/cookies.d.ts +28 -0
  59. package/dist/cookies.d.ts.map +1 -0
  60. package/dist/cookies.js +95 -0
  61. package/dist/esm/activity.d.ts +59 -0
  62. package/dist/esm/activity.d.ts.map +1 -0
  63. package/dist/esm/activity.js +127 -0
  64. package/dist/esm/activity.js.map +1 -0
  65. package/dist/esm/consent.d.ts +68 -0
  66. package/dist/esm/consent.d.ts.map +1 -0
  67. package/dist/esm/consent.js +187 -0
  68. package/dist/esm/consent.js.map +1 -0
  69. package/dist/esm/cookies.d.ts +28 -0
  70. package/dist/esm/cookies.d.ts.map +1 -0
  71. package/dist/esm/cookies.js +89 -0
  72. package/dist/esm/cookies.js.map +1 -0
  73. package/dist/esm/heartbeat.d.ts +42 -0
  74. package/dist/esm/heartbeat.d.ts.map +1 -0
  75. package/dist/esm/heartbeat.js +88 -0
  76. package/dist/esm/heartbeat.js.map +1 -0
  77. package/dist/esm/index.d.ts +100 -3
  78. package/dist/esm/index.d.ts.map +1 -1
  79. package/dist/esm/index.js.map +1 -1
  80. package/dist/esm/page-tracking.d.ts +60 -0
  81. package/dist/esm/page-tracking.d.ts.map +1 -0
  82. package/dist/esm/page-tracking.js +176 -0
  83. package/dist/esm/page-tracking.js.map +1 -0
  84. package/dist/esm/react/components/ConsentBanner.d.ts +16 -0
  85. package/dist/esm/react/components/ConsentBanner.d.ts.map +1 -0
  86. package/dist/esm/react/components/ConsentBanner.js +76 -0
  87. package/dist/esm/react/components/ConsentBanner.js.map +1 -0
  88. package/dist/esm/react/components/CookieNotice.d.ts +12 -0
  89. package/dist/esm/react/components/CookieNotice.d.ts.map +1 -0
  90. package/dist/esm/react/components/CookieNotice.js +26 -0
  91. package/dist/esm/react/components/CookieNotice.js.map +1 -0
  92. package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  93. package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  94. package/dist/esm/react/components/PrivacyPreferenceCenter.js +84 -0
  95. package/dist/esm/react/components/PrivacyPreferenceCenter.js.map +1 -0
  96. package/dist/esm/react/hooks/useConsent.d.ts +13 -0
  97. package/dist/esm/react/hooks/useConsent.d.ts.map +1 -0
  98. package/dist/esm/react/hooks/useConsent.js +48 -0
  99. package/dist/esm/react/hooks/useConsent.js.map +1 -0
  100. package/dist/esm/react/hooks/useDataDeletion.d.ts +17 -0
  101. package/dist/esm/react/hooks/useDataDeletion.d.ts.map +1 -0
  102. package/dist/esm/react/hooks/useDataDeletion.js +81 -0
  103. package/dist/esm/react/hooks/useDataDeletion.js.map +1 -0
  104. package/dist/esm/react/hooks/usePrivacyPreferences.d.ts +15 -0
  105. package/dist/esm/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  106. package/dist/esm/react/hooks/usePrivacyPreferences.js +46 -0
  107. package/dist/esm/react/hooks/usePrivacyPreferences.js.map +1 -0
  108. package/dist/esm/react/index.d.ts +11 -0
  109. package/dist/esm/react/index.d.ts.map +1 -1
  110. package/dist/esm/react/index.js +8 -0
  111. package/dist/esm/react/index.js.map +1 -1
  112. package/dist/heartbeat.d.ts +42 -0
  113. package/dist/heartbeat.d.ts.map +1 -0
  114. package/dist/heartbeat.js +92 -0
  115. package/dist/index.d.ts +100 -3
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.global.dev.js +903 -12
  118. package/dist/index.global.dev.js.map +3 -3
  119. package/dist/index.global.js +2 -2
  120. package/dist/index.global.js.map +4 -4
  121. package/dist/index.js +321 -11
  122. package/dist/index.mjs +321 -11
  123. package/dist/page-tracking.d.ts +60 -0
  124. package/dist/page-tracking.d.ts.map +1 -0
  125. package/dist/page-tracking.js +180 -0
  126. package/dist/react/activity.d.ts +59 -0
  127. package/dist/react/activity.d.ts.map +1 -0
  128. package/dist/react/activity.js +130 -0
  129. package/dist/react/activity.mjs +126 -0
  130. package/dist/react/consent.d.ts +68 -0
  131. package/dist/react/consent.d.ts.map +1 -0
  132. package/dist/react/consent.js +190 -0
  133. package/dist/react/consent.mjs +186 -0
  134. package/dist/react/cookies.d.ts +28 -0
  135. package/dist/react/cookies.d.ts.map +1 -0
  136. package/dist/react/cookies.js +94 -0
  137. package/dist/react/cookies.mjs +88 -0
  138. package/dist/react/heartbeat.d.ts +42 -0
  139. package/dist/react/heartbeat.d.ts.map +1 -0
  140. package/dist/react/heartbeat.js +91 -0
  141. package/dist/react/heartbeat.mjs +87 -0
  142. package/dist/react/index.d.ts +100 -3
  143. package/dist/react/index.d.ts.map +1 -1
  144. package/dist/react/index.js +321 -11
  145. package/dist/react/index.mjs +321 -11
  146. package/dist/react/page-tracking.d.ts +60 -0
  147. package/dist/react/page-tracking.d.ts.map +1 -0
  148. package/dist/react/page-tracking.js +179 -0
  149. package/dist/react/page-tracking.mjs +175 -0
  150. package/dist/react/react/components/ConsentBanner.d.ts +16 -0
  151. package/dist/react/react/components/ConsentBanner.d.ts.map +1 -0
  152. package/dist/react/react/components/ConsentBanner.js +78 -0
  153. package/dist/react/react/components/ConsentBanner.mjs +75 -0
  154. package/dist/react/react/components/CookieNotice.d.ts +12 -0
  155. package/dist/react/react/components/CookieNotice.d.ts.map +1 -0
  156. package/dist/react/react/components/CookieNotice.js +28 -0
  157. package/dist/react/react/components/CookieNotice.mjs +25 -0
  158. package/dist/react/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  159. package/dist/react/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  160. package/dist/react/react/components/PrivacyPreferenceCenter.js +86 -0
  161. package/dist/react/react/components/PrivacyPreferenceCenter.mjs +83 -0
  162. package/dist/react/react/hooks/useConsent.d.ts +13 -0
  163. package/dist/react/react/hooks/useConsent.d.ts.map +1 -0
  164. package/dist/react/react/hooks/useConsent.js +50 -0
  165. package/dist/react/react/hooks/useConsent.mjs +47 -0
  166. package/dist/react/react/hooks/useDataDeletion.d.ts +17 -0
  167. package/dist/react/react/hooks/useDataDeletion.d.ts.map +1 -0
  168. package/dist/react/react/hooks/useDataDeletion.js +83 -0
  169. package/dist/react/react/hooks/useDataDeletion.mjs +80 -0
  170. package/dist/react/react/hooks/usePrivacyPreferences.d.ts +15 -0
  171. package/dist/react/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  172. package/dist/react/react/hooks/usePrivacyPreferences.js +48 -0
  173. package/dist/react/react/hooks/usePrivacyPreferences.mjs +45 -0
  174. package/dist/react/react/index.d.ts +11 -0
  175. package/dist/react/react/index.d.ts.map +1 -1
  176. package/dist/react/react/index.js +15 -1
  177. package/dist/react/react/index.mjs +8 -0
  178. package/package.json +3 -3
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ /**
3
+ * Page Tracking for Grain Analytics
4
+ * Automatically tracks page views with consent-aware behavior
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.PageTrackingManager = void 0;
8
+ class PageTrackingManager {
9
+ constructor(tracker, config) {
10
+ this.isDestroyed = false;
11
+ this.currentPath = null;
12
+ this.originalPushState = null;
13
+ this.originalReplaceState = null;
14
+ /**
15
+ * Handle popstate event (back/forward navigation)
16
+ */
17
+ this.handlePopState = () => {
18
+ if (this.isDestroyed)
19
+ return;
20
+ this.trackCurrentPage();
21
+ };
22
+ /**
23
+ * Handle hash change event
24
+ */
25
+ this.handleHashChange = () => {
26
+ if (this.isDestroyed)
27
+ return;
28
+ this.trackCurrentPage();
29
+ };
30
+ this.tracker = tracker;
31
+ this.config = config;
32
+ // Track initial page load
33
+ this.trackCurrentPage();
34
+ // Setup listeners
35
+ this.setupHistoryListeners();
36
+ this.setupHashChangeListener();
37
+ }
38
+ /**
39
+ * Setup History API listeners (pushState, replaceState, popstate)
40
+ */
41
+ setupHistoryListeners() {
42
+ if (typeof window === 'undefined' || typeof history === 'undefined')
43
+ return;
44
+ // Wrap pushState
45
+ this.originalPushState = history.pushState;
46
+ history.pushState = (state, title, url) => {
47
+ this.originalPushState?.call(history, state, title, url);
48
+ this.trackCurrentPage();
49
+ };
50
+ // Wrap replaceState
51
+ this.originalReplaceState = history.replaceState;
52
+ history.replaceState = (state, title, url) => {
53
+ this.originalReplaceState?.call(history, state, title, url);
54
+ this.trackCurrentPage();
55
+ };
56
+ // Listen to popstate (back/forward buttons)
57
+ window.addEventListener('popstate', this.handlePopState);
58
+ }
59
+ /**
60
+ * Setup hash change listener
61
+ */
62
+ setupHashChangeListener() {
63
+ if (typeof window === 'undefined')
64
+ return;
65
+ window.addEventListener('hashchange', this.handleHashChange);
66
+ }
67
+ /**
68
+ * Track the current page
69
+ */
70
+ trackCurrentPage() {
71
+ if (this.isDestroyed || typeof window === 'undefined')
72
+ return;
73
+ const page = this.extractPath(window.location.href);
74
+ // Don't track if it's the same page
75
+ if (page === this.currentPath) {
76
+ return;
77
+ }
78
+ this.currentPath = page;
79
+ const hasConsent = this.tracker.hasConsent('analytics');
80
+ // Base properties (always included)
81
+ const properties = {
82
+ page,
83
+ timestamp: Date.now(),
84
+ };
85
+ // Enhanced properties when consent is granted
86
+ if (hasConsent) {
87
+ properties.referrer = document.referrer || '';
88
+ properties.title = document.title || '';
89
+ properties.full_url = window.location.href;
90
+ }
91
+ // Track the page view event
92
+ this.tracker.trackSystemEvent('page_view', properties);
93
+ if (this.config.debug) {
94
+ console.log('[Page Tracking] Tracked page view:', properties);
95
+ }
96
+ }
97
+ /**
98
+ * Extract path from URL, optionally stripping query parameters
99
+ */
100
+ extractPath(url) {
101
+ try {
102
+ const urlObj = new URL(url);
103
+ let path = urlObj.pathname + urlObj.hash;
104
+ if (!this.config.stripQueryParams && urlObj.search) {
105
+ path += urlObj.search;
106
+ }
107
+ return path;
108
+ }
109
+ catch (error) {
110
+ // If URL parsing fails, return the raw string
111
+ if (this.config.debug) {
112
+ console.warn('[Page Tracking] Failed to parse URL:', url, error);
113
+ }
114
+ return url;
115
+ }
116
+ }
117
+ /**
118
+ * Get the current page path
119
+ */
120
+ getCurrentPage() {
121
+ return this.currentPath;
122
+ }
123
+ /**
124
+ * Manually track a page view (for custom navigation)
125
+ */
126
+ trackPage(page, properties) {
127
+ if (this.isDestroyed)
128
+ return;
129
+ const hasConsent = this.tracker.hasConsent('analytics');
130
+ // Base properties
131
+ const baseProperties = {
132
+ page,
133
+ timestamp: Date.now(),
134
+ ...properties,
135
+ };
136
+ // Enhanced properties when consent is granted
137
+ if (hasConsent && typeof document !== 'undefined') {
138
+ if (!baseProperties.referrer) {
139
+ baseProperties.referrer = document.referrer || '';
140
+ }
141
+ if (!baseProperties.title) {
142
+ baseProperties.title = document.title || '';
143
+ }
144
+ if (!baseProperties.full_url && typeof window !== 'undefined') {
145
+ baseProperties.full_url = window.location.href;
146
+ }
147
+ }
148
+ this.tracker.trackSystemEvent('page_view', baseProperties);
149
+ if (this.config.debug) {
150
+ console.log('[Page Tracking] Manually tracked page:', baseProperties);
151
+ }
152
+ }
153
+ /**
154
+ * Destroy the page tracker
155
+ */
156
+ destroy() {
157
+ if (this.isDestroyed)
158
+ return;
159
+ // Restore original history methods
160
+ if (typeof history !== 'undefined') {
161
+ if (this.originalPushState) {
162
+ history.pushState = this.originalPushState;
163
+ }
164
+ if (this.originalReplaceState) {
165
+ history.replaceState = this.originalReplaceState;
166
+ }
167
+ }
168
+ // Remove event listeners
169
+ if (typeof window !== 'undefined') {
170
+ window.removeEventListener('popstate', this.handlePopState);
171
+ window.removeEventListener('hashchange', this.handleHashChange);
172
+ }
173
+ this.isDestroyed = true;
174
+ if (this.config.debug) {
175
+ console.log('[Page Tracking] Destroyed');
176
+ }
177
+ }
178
+ }
179
+ exports.PageTrackingManager = PageTrackingManager;
180
+ //# sourceMappingURL=page-tracking.js.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Activity Detection for Grain Analytics
3
+ * Tracks user activity (mouse, keyboard, touch, scroll) to determine if user is active
4
+ */
5
+ export declare class ActivityDetector {
6
+ private lastActivityTime;
7
+ private activityThreshold;
8
+ private listeners;
9
+ private boundActivityHandler;
10
+ private isDestroyed;
11
+ private readonly activityEvents;
12
+ constructor();
13
+ /**
14
+ * Setup event listeners for activity detection
15
+ */
16
+ private setupListeners;
17
+ /**
18
+ * Handle activity event
19
+ */
20
+ private handleActivity;
21
+ /**
22
+ * Debounce function to limit how often activity handler is called
23
+ */
24
+ private debounce;
25
+ /**
26
+ * Check if user is currently active
27
+ * @param threshold Time in ms to consider user inactive (default: 30s)
28
+ */
29
+ isActive(threshold?: number): boolean;
30
+ /**
31
+ * Get time since last activity in milliseconds
32
+ */
33
+ getTimeSinceLastActivity(): number;
34
+ /**
35
+ * Get last activity timestamp
36
+ */
37
+ getLastActivityTime(): number;
38
+ /**
39
+ * Set activity threshold
40
+ */
41
+ setActivityThreshold(threshold: number): void;
42
+ /**
43
+ * Add listener for activity changes
44
+ */
45
+ addListener(listener: () => void): void;
46
+ /**
47
+ * Remove listener
48
+ */
49
+ removeListener(listener: () => void): void;
50
+ /**
51
+ * Notify all listeners
52
+ */
53
+ private notifyListeners;
54
+ /**
55
+ * Cleanup and remove listeners
56
+ */
57
+ destroy(): void;
58
+ }
59
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/activity.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAOpB;;IAQX;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAehB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO;IAMrC;;OAEG;IACH,wBAAwB,IAAI,MAAM;IAIlC;;OAEG;IACH,mBAAmB,IAAI,MAAM;IAI7B;;OAEG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI7C;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIvC;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAO1C;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,IAAI,IAAI;CAYhB"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ /**
3
+ * Activity Detection for Grain Analytics
4
+ * Tracks user activity (mouse, keyboard, touch, scroll) to determine if user is active
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ActivityDetector = void 0;
8
+ class ActivityDetector {
9
+ constructor() {
10
+ this.activityThreshold = 30000; // 30 seconds
11
+ this.listeners = [];
12
+ this.isDestroyed = false;
13
+ // Events that indicate user activity
14
+ this.activityEvents = [
15
+ 'mousemove',
16
+ 'mousedown',
17
+ 'keydown',
18
+ 'scroll',
19
+ 'touchstart',
20
+ 'click',
21
+ ];
22
+ this.lastActivityTime = Date.now();
23
+ this.boundActivityHandler = this.debounce(this.handleActivity.bind(this), 500);
24
+ this.setupListeners();
25
+ }
26
+ /**
27
+ * Setup event listeners for activity detection
28
+ */
29
+ setupListeners() {
30
+ if (typeof window === 'undefined')
31
+ return;
32
+ for (const event of this.activityEvents) {
33
+ window.addEventListener(event, this.boundActivityHandler, { passive: true });
34
+ }
35
+ }
36
+ /**
37
+ * Handle activity event
38
+ */
39
+ handleActivity() {
40
+ if (this.isDestroyed)
41
+ return;
42
+ this.lastActivityTime = Date.now();
43
+ this.notifyListeners();
44
+ }
45
+ /**
46
+ * Debounce function to limit how often activity handler is called
47
+ */
48
+ debounce(func, wait) {
49
+ let timeout = null;
50
+ return () => {
51
+ if (timeout !== null) {
52
+ clearTimeout(timeout);
53
+ }
54
+ timeout = window.setTimeout(() => {
55
+ func();
56
+ timeout = null;
57
+ }, wait);
58
+ };
59
+ }
60
+ /**
61
+ * Check if user is currently active
62
+ * @param threshold Time in ms to consider user inactive (default: 30s)
63
+ */
64
+ isActive(threshold) {
65
+ const thresholdToUse = threshold ?? this.activityThreshold;
66
+ const now = Date.now();
67
+ return (now - this.lastActivityTime) < thresholdToUse;
68
+ }
69
+ /**
70
+ * Get time since last activity in milliseconds
71
+ */
72
+ getTimeSinceLastActivity() {
73
+ return Date.now() - this.lastActivityTime;
74
+ }
75
+ /**
76
+ * Get last activity timestamp
77
+ */
78
+ getLastActivityTime() {
79
+ return this.lastActivityTime;
80
+ }
81
+ /**
82
+ * Set activity threshold
83
+ */
84
+ setActivityThreshold(threshold) {
85
+ this.activityThreshold = threshold;
86
+ }
87
+ /**
88
+ * Add listener for activity changes
89
+ */
90
+ addListener(listener) {
91
+ this.listeners.push(listener);
92
+ }
93
+ /**
94
+ * Remove listener
95
+ */
96
+ removeListener(listener) {
97
+ const index = this.listeners.indexOf(listener);
98
+ if (index > -1) {
99
+ this.listeners.splice(index, 1);
100
+ }
101
+ }
102
+ /**
103
+ * Notify all listeners
104
+ */
105
+ notifyListeners() {
106
+ for (const listener of this.listeners) {
107
+ try {
108
+ listener();
109
+ }
110
+ catch (error) {
111
+ console.error('[Activity Detector] Listener error:', error);
112
+ }
113
+ }
114
+ }
115
+ /**
116
+ * Cleanup and remove listeners
117
+ */
118
+ destroy() {
119
+ if (this.isDestroyed)
120
+ return;
121
+ if (typeof window !== 'undefined') {
122
+ for (const event of this.activityEvents) {
123
+ window.removeEventListener(event, this.boundActivityHandler);
124
+ }
125
+ }
126
+ this.listeners = [];
127
+ this.isDestroyed = true;
128
+ }
129
+ }
130
+ exports.ActivityDetector = ActivityDetector;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Activity Detection for Grain Analytics
3
+ * Tracks user activity (mouse, keyboard, touch, scroll) to determine if user is active
4
+ */
5
+ export class ActivityDetector {
6
+ constructor() {
7
+ this.activityThreshold = 30000; // 30 seconds
8
+ this.listeners = [];
9
+ this.isDestroyed = false;
10
+ // Events that indicate user activity
11
+ this.activityEvents = [
12
+ 'mousemove',
13
+ 'mousedown',
14
+ 'keydown',
15
+ 'scroll',
16
+ 'touchstart',
17
+ 'click',
18
+ ];
19
+ this.lastActivityTime = Date.now();
20
+ this.boundActivityHandler = this.debounce(this.handleActivity.bind(this), 500);
21
+ this.setupListeners();
22
+ }
23
+ /**
24
+ * Setup event listeners for activity detection
25
+ */
26
+ setupListeners() {
27
+ if (typeof window === 'undefined')
28
+ return;
29
+ for (const event of this.activityEvents) {
30
+ window.addEventListener(event, this.boundActivityHandler, { passive: true });
31
+ }
32
+ }
33
+ /**
34
+ * Handle activity event
35
+ */
36
+ handleActivity() {
37
+ if (this.isDestroyed)
38
+ return;
39
+ this.lastActivityTime = Date.now();
40
+ this.notifyListeners();
41
+ }
42
+ /**
43
+ * Debounce function to limit how often activity handler is called
44
+ */
45
+ debounce(func, wait) {
46
+ let timeout = null;
47
+ return () => {
48
+ if (timeout !== null) {
49
+ clearTimeout(timeout);
50
+ }
51
+ timeout = window.setTimeout(() => {
52
+ func();
53
+ timeout = null;
54
+ }, wait);
55
+ };
56
+ }
57
+ /**
58
+ * Check if user is currently active
59
+ * @param threshold Time in ms to consider user inactive (default: 30s)
60
+ */
61
+ isActive(threshold) {
62
+ const thresholdToUse = threshold ?? this.activityThreshold;
63
+ const now = Date.now();
64
+ return (now - this.lastActivityTime) < thresholdToUse;
65
+ }
66
+ /**
67
+ * Get time since last activity in milliseconds
68
+ */
69
+ getTimeSinceLastActivity() {
70
+ return Date.now() - this.lastActivityTime;
71
+ }
72
+ /**
73
+ * Get last activity timestamp
74
+ */
75
+ getLastActivityTime() {
76
+ return this.lastActivityTime;
77
+ }
78
+ /**
79
+ * Set activity threshold
80
+ */
81
+ setActivityThreshold(threshold) {
82
+ this.activityThreshold = threshold;
83
+ }
84
+ /**
85
+ * Add listener for activity changes
86
+ */
87
+ addListener(listener) {
88
+ this.listeners.push(listener);
89
+ }
90
+ /**
91
+ * Remove listener
92
+ */
93
+ removeListener(listener) {
94
+ const index = this.listeners.indexOf(listener);
95
+ if (index > -1) {
96
+ this.listeners.splice(index, 1);
97
+ }
98
+ }
99
+ /**
100
+ * Notify all listeners
101
+ */
102
+ notifyListeners() {
103
+ for (const listener of this.listeners) {
104
+ try {
105
+ listener();
106
+ }
107
+ catch (error) {
108
+ console.error('[Activity Detector] Listener error:', error);
109
+ }
110
+ }
111
+ }
112
+ /**
113
+ * Cleanup and remove listeners
114
+ */
115
+ destroy() {
116
+ if (this.isDestroyed)
117
+ return;
118
+ if (typeof window !== 'undefined') {
119
+ for (const event of this.activityEvents) {
120
+ window.removeEventListener(event, this.boundActivityHandler);
121
+ }
122
+ }
123
+ this.listeners = [];
124
+ this.isDestroyed = true;
125
+ }
126
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Consent management for Grain Analytics
3
+ * Handles GDPR-compliant consent tracking and state management
4
+ */
5
+ export type ConsentMode = 'opt-in' | 'opt-out' | 'disabled';
6
+ export interface ConsentState {
7
+ granted: boolean;
8
+ categories: string[];
9
+ timestamp: Date;
10
+ version: string;
11
+ }
12
+ export declare const DEFAULT_CONSENT_CATEGORIES: string[];
13
+ export declare const CONSENT_VERSION = "1.0.0";
14
+ /**
15
+ * Consent manager for handling user consent state
16
+ */
17
+ export declare class ConsentManager {
18
+ private consentState;
19
+ private consentMode;
20
+ private storageKey;
21
+ private listeners;
22
+ constructor(tenantId: string, consentMode?: ConsentMode);
23
+ /**
24
+ * Load consent state from localStorage
25
+ */
26
+ private loadConsentState;
27
+ /**
28
+ * Save consent state to localStorage
29
+ */
30
+ private saveConsentState;
31
+ /**
32
+ * Grant consent with optional categories
33
+ */
34
+ grantConsent(categories?: string[]): void;
35
+ /**
36
+ * Revoke consent (opt-out)
37
+ */
38
+ revokeConsent(categories?: string[]): void;
39
+ /**
40
+ * Get current consent state
41
+ */
42
+ getConsentState(): ConsentState | null;
43
+ /**
44
+ * Check if user has granted consent
45
+ */
46
+ hasConsent(category?: string): boolean;
47
+ /**
48
+ * Check if we should wait for consent before tracking
49
+ */
50
+ shouldWaitForConsent(): boolean;
51
+ /**
52
+ * Add consent change listener
53
+ */
54
+ addListener(listener: (state: ConsentState) => void): void;
55
+ /**
56
+ * Remove consent change listener
57
+ */
58
+ removeListener(listener: (state: ConsentState) => void): void;
59
+ /**
60
+ * Notify all listeners of consent state change
61
+ */
62
+ private notifyListeners;
63
+ /**
64
+ * Clear all consent data
65
+ */
66
+ clearConsent(): void;
67
+ }
68
+ //# sourceMappingURL=consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/consent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,0BAA0B,UAA2C,CAAC;AACnF,eAAO,MAAM,eAAe,UAAU,CAAC;AAEvC;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAA4C;gBAEjD,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAE,WAAuB;IAMlE;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IAczC;;OAEG;IACH,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;IA8B1C;;OAEG;IACH,eAAe,IAAI,YAAY,GAAG,IAAI;IAItC;;OAEG;IACH,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAwBtC;;OAEG;IACH,oBAAoB,IAAI,OAAO;IAI/B;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAI1D;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAO7D;;OAEG;IACH,OAAO,CAAC,eAAe;IAYvB;;OAEG;IACH,YAAY,IAAI,IAAI;CAUrB"}