@grainql/analytics-web 1.7.4 → 2.1.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.
Files changed (258) hide show
  1. package/README.md +71 -718
  2. package/dist/activity.d.ts +59 -0
  3. package/dist/activity.d.ts.map +1 -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/GrainProvider.d.ts +11 -0
  28. package/dist/cjs/react/GrainProvider.d.ts.map +1 -0
  29. package/dist/cjs/react/GrainProvider.js +79 -0
  30. package/dist/cjs/react/GrainProvider.js.map +1 -0
  31. package/dist/cjs/react/components/ConsentBanner.d.ts +16 -0
  32. package/dist/cjs/react/components/ConsentBanner.d.ts.map +1 -0
  33. package/dist/cjs/react/components/ConsentBanner.js +112 -0
  34. package/dist/cjs/react/components/ConsentBanner.js.map +1 -0
  35. package/dist/cjs/react/components/CookieNotice.d.ts +12 -0
  36. package/dist/cjs/react/components/CookieNotice.d.ts.map +1 -0
  37. package/dist/cjs/react/components/CookieNotice.js +62 -0
  38. package/dist/cjs/react/components/CookieNotice.js.map +1 -0
  39. package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  40. package/dist/cjs/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  41. package/dist/cjs/react/components/PrivacyPreferenceCenter.js +120 -0
  42. package/dist/cjs/react/components/PrivacyPreferenceCenter.js.map +1 -0
  43. package/dist/cjs/react/context.d.ts +11 -0
  44. package/dist/cjs/react/context.d.ts.map +1 -0
  45. package/dist/cjs/react/context.js +43 -0
  46. package/dist/cjs/react/context.js.map +1 -0
  47. package/dist/cjs/react/hooks/useAllConfigs.d.ts +8 -0
  48. package/dist/cjs/react/hooks/useAllConfigs.d.ts.map +1 -0
  49. package/dist/cjs/react/hooks/useAllConfigs.js +112 -0
  50. package/dist/cjs/react/hooks/useAllConfigs.js.map +1 -0
  51. package/dist/cjs/react/hooks/useConfig.d.ts +9 -0
  52. package/dist/cjs/react/hooks/useConfig.d.ts.map +1 -0
  53. package/dist/cjs/react/hooks/useConfig.js +116 -0
  54. package/dist/cjs/react/hooks/useConfig.js.map +1 -0
  55. package/dist/cjs/react/hooks/useConsent.d.ts +13 -0
  56. package/dist/cjs/react/hooks/useConsent.d.ts.map +1 -0
  57. package/dist/cjs/react/hooks/useConsent.js +84 -0
  58. package/dist/cjs/react/hooks/useConsent.js.map +1 -0
  59. package/dist/cjs/react/hooks/useDataDeletion.d.ts +17 -0
  60. package/dist/cjs/react/hooks/useDataDeletion.d.ts.map +1 -0
  61. package/dist/cjs/react/hooks/useDataDeletion.js +117 -0
  62. package/dist/cjs/react/hooks/useDataDeletion.js.map +1 -0
  63. package/dist/cjs/react/hooks/useGrainAnalytics.d.ts +6 -0
  64. package/dist/cjs/react/hooks/useGrainAnalytics.d.ts.map +1 -0
  65. package/dist/cjs/react/hooks/useGrainAnalytics.js +50 -0
  66. package/dist/cjs/react/hooks/useGrainAnalytics.js.map +1 -0
  67. package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts +15 -0
  68. package/dist/cjs/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  69. package/dist/cjs/react/hooks/usePrivacyPreferences.js +82 -0
  70. package/dist/cjs/react/hooks/usePrivacyPreferences.js.map +1 -0
  71. package/dist/cjs/react/hooks/useTrack.d.ts +9 -0
  72. package/dist/cjs/react/hooks/useTrack.d.ts.map +1 -0
  73. package/dist/cjs/react/hooks/useTrack.js +53 -0
  74. package/dist/cjs/react/hooks/useTrack.js.map +1 -0
  75. package/dist/cjs/react/index.d.ts +47 -0
  76. package/dist/cjs/react/index.d.ts.map +1 -0
  77. package/dist/cjs/react/index.js +59 -0
  78. package/dist/cjs/react/index.js.map +1 -0
  79. package/dist/cjs/react/types.d.ts +33 -0
  80. package/dist/cjs/react/types.d.ts.map +1 -0
  81. package/dist/cjs/react/types.js +6 -0
  82. package/dist/cjs/react/types.js.map +1 -0
  83. package/dist/consent.d.ts +68 -0
  84. package/dist/consent.d.ts.map +1 -0
  85. package/dist/cookies.d.ts +28 -0
  86. package/dist/cookies.d.ts.map +1 -0
  87. package/dist/esm/activity.d.ts +59 -0
  88. package/dist/esm/activity.d.ts.map +1 -0
  89. package/dist/esm/activity.js +127 -0
  90. package/dist/esm/activity.js.map +1 -0
  91. package/dist/esm/consent.d.ts +68 -0
  92. package/dist/esm/consent.d.ts.map +1 -0
  93. package/dist/esm/consent.js +187 -0
  94. package/dist/esm/consent.js.map +1 -0
  95. package/dist/esm/cookies.d.ts +28 -0
  96. package/dist/esm/cookies.d.ts.map +1 -0
  97. package/dist/esm/cookies.js +89 -0
  98. package/dist/esm/cookies.js.map +1 -0
  99. package/dist/esm/heartbeat.d.ts +42 -0
  100. package/dist/esm/heartbeat.d.ts.map +1 -0
  101. package/dist/esm/heartbeat.js +88 -0
  102. package/dist/esm/heartbeat.js.map +1 -0
  103. package/dist/esm/index.d.ts +100 -3
  104. package/dist/esm/index.d.ts.map +1 -1
  105. package/dist/esm/index.js.map +1 -1
  106. package/dist/esm/page-tracking.d.ts +60 -0
  107. package/dist/esm/page-tracking.d.ts.map +1 -0
  108. package/dist/esm/page-tracking.js +176 -0
  109. package/dist/esm/page-tracking.js.map +1 -0
  110. package/dist/esm/react/GrainProvider.d.ts +11 -0
  111. package/dist/esm/react/GrainProvider.d.ts.map +1 -0
  112. package/dist/esm/react/GrainProvider.js +43 -0
  113. package/dist/esm/react/GrainProvider.js.map +1 -0
  114. package/dist/esm/react/components/ConsentBanner.d.ts +16 -0
  115. package/dist/esm/react/components/ConsentBanner.d.ts.map +1 -0
  116. package/dist/esm/react/components/ConsentBanner.js +76 -0
  117. package/dist/esm/react/components/ConsentBanner.js.map +1 -0
  118. package/dist/esm/react/components/CookieNotice.d.ts +12 -0
  119. package/dist/esm/react/components/CookieNotice.d.ts.map +1 -0
  120. package/dist/esm/react/components/CookieNotice.js +26 -0
  121. package/dist/esm/react/components/CookieNotice.js.map +1 -0
  122. package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  123. package/dist/esm/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  124. package/dist/esm/react/components/PrivacyPreferenceCenter.js +84 -0
  125. package/dist/esm/react/components/PrivacyPreferenceCenter.js.map +1 -0
  126. package/dist/esm/react/context.d.ts +11 -0
  127. package/dist/esm/react/context.d.ts.map +1 -0
  128. package/dist/esm/react/context.js +7 -0
  129. package/dist/esm/react/context.js.map +1 -0
  130. package/dist/esm/react/hooks/useAllConfigs.d.ts +8 -0
  131. package/dist/esm/react/hooks/useAllConfigs.d.ts.map +1 -0
  132. package/dist/esm/react/hooks/useAllConfigs.js +76 -0
  133. package/dist/esm/react/hooks/useAllConfigs.js.map +1 -0
  134. package/dist/esm/react/hooks/useConfig.d.ts +9 -0
  135. package/dist/esm/react/hooks/useConfig.d.ts.map +1 -0
  136. package/dist/esm/react/hooks/useConfig.js +80 -0
  137. package/dist/esm/react/hooks/useConfig.js.map +1 -0
  138. package/dist/esm/react/hooks/useConsent.d.ts +13 -0
  139. package/dist/esm/react/hooks/useConsent.d.ts.map +1 -0
  140. package/dist/esm/react/hooks/useConsent.js +48 -0
  141. package/dist/esm/react/hooks/useConsent.js.map +1 -0
  142. package/dist/esm/react/hooks/useDataDeletion.d.ts +17 -0
  143. package/dist/esm/react/hooks/useDataDeletion.d.ts.map +1 -0
  144. package/dist/esm/react/hooks/useDataDeletion.js +81 -0
  145. package/dist/esm/react/hooks/useDataDeletion.js.map +1 -0
  146. package/dist/esm/react/hooks/useGrainAnalytics.d.ts +6 -0
  147. package/dist/esm/react/hooks/useGrainAnalytics.d.ts.map +1 -0
  148. package/dist/esm/react/hooks/useGrainAnalytics.js +14 -0
  149. package/dist/esm/react/hooks/useGrainAnalytics.js.map +1 -0
  150. package/dist/esm/react/hooks/usePrivacyPreferences.d.ts +15 -0
  151. package/dist/esm/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  152. package/dist/esm/react/hooks/usePrivacyPreferences.js +46 -0
  153. package/dist/esm/react/hooks/usePrivacyPreferences.js.map +1 -0
  154. package/dist/esm/react/hooks/useTrack.d.ts +9 -0
  155. package/dist/esm/react/hooks/useTrack.d.ts.map +1 -0
  156. package/dist/esm/react/hooks/useTrack.js +17 -0
  157. package/dist/esm/react/hooks/useTrack.js.map +1 -0
  158. package/dist/esm/react/index.d.ts +47 -0
  159. package/dist/esm/react/index.d.ts.map +1 -0
  160. package/dist/esm/react/index.js +45 -0
  161. package/dist/esm/react/index.js.map +1 -0
  162. package/dist/esm/react/types.d.ts +33 -0
  163. package/dist/esm/react/types.d.ts.map +1 -0
  164. package/dist/esm/react/types.js +5 -0
  165. package/dist/esm/react/types.js.map +1 -0
  166. package/dist/heartbeat.d.ts +42 -0
  167. package/dist/heartbeat.d.ts.map +1 -0
  168. package/dist/index.d.ts +100 -3
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.global.dev.js +903 -12
  171. package/dist/index.global.dev.js.map +3 -3
  172. package/dist/index.global.js +2 -2
  173. package/dist/index.global.js.map +4 -4
  174. package/dist/index.js +321 -11
  175. package/dist/index.mjs +321 -11
  176. package/dist/page-tracking.d.ts +60 -0
  177. package/dist/page-tracking.d.ts.map +1 -0
  178. package/dist/react/activity.d.ts +59 -0
  179. package/dist/react/activity.d.ts.map +1 -0
  180. package/dist/react/activity.js +130 -0
  181. package/dist/react/activity.mjs +126 -0
  182. package/dist/react/consent.d.ts +68 -0
  183. package/dist/react/consent.d.ts.map +1 -0
  184. package/dist/react/consent.js +190 -0
  185. package/dist/react/consent.mjs +186 -0
  186. package/dist/react/cookies.d.ts +28 -0
  187. package/dist/react/cookies.d.ts.map +1 -0
  188. package/dist/react/cookies.js +94 -0
  189. package/dist/react/cookies.mjs +88 -0
  190. package/dist/react/heartbeat.d.ts +42 -0
  191. package/dist/react/heartbeat.d.ts.map +1 -0
  192. package/dist/react/heartbeat.js +91 -0
  193. package/dist/react/heartbeat.mjs +87 -0
  194. package/dist/react/index.d.ts +502 -0
  195. package/dist/react/index.d.ts.map +1 -0
  196. package/dist/react/index.js +1491 -0
  197. package/dist/react/index.mjs +1486 -0
  198. package/dist/react/page-tracking.d.ts +60 -0
  199. package/dist/react/page-tracking.d.ts.map +1 -0
  200. package/dist/react/page-tracking.js +179 -0
  201. package/dist/react/page-tracking.mjs +175 -0
  202. package/dist/react/react/GrainProvider.d.ts +11 -0
  203. package/dist/react/react/GrainProvider.d.ts.map +1 -0
  204. package/dist/react/react/GrainProvider.js +45 -0
  205. package/dist/react/react/GrainProvider.mjs +42 -0
  206. package/dist/react/react/components/ConsentBanner.d.ts +16 -0
  207. package/dist/react/react/components/ConsentBanner.d.ts.map +1 -0
  208. package/dist/react/react/components/ConsentBanner.js +78 -0
  209. package/dist/react/react/components/ConsentBanner.mjs +75 -0
  210. package/dist/react/react/components/CookieNotice.d.ts +12 -0
  211. package/dist/react/react/components/CookieNotice.d.ts.map +1 -0
  212. package/dist/react/react/components/CookieNotice.js +28 -0
  213. package/dist/react/react/components/CookieNotice.mjs +25 -0
  214. package/dist/react/react/components/PrivacyPreferenceCenter.d.ts +12 -0
  215. package/dist/react/react/components/PrivacyPreferenceCenter.d.ts.map +1 -0
  216. package/dist/react/react/components/PrivacyPreferenceCenter.js +86 -0
  217. package/dist/react/react/components/PrivacyPreferenceCenter.mjs +83 -0
  218. package/dist/react/react/context.d.ts +11 -0
  219. package/dist/react/react/context.d.ts.map +1 -0
  220. package/dist/react/react/context.js +9 -0
  221. package/dist/react/react/context.mjs +6 -0
  222. package/dist/react/react/hooks/useAllConfigs.d.ts +8 -0
  223. package/dist/react/react/hooks/useAllConfigs.d.ts.map +1 -0
  224. package/dist/react/react/hooks/useAllConfigs.js +78 -0
  225. package/dist/react/react/hooks/useAllConfigs.mjs +75 -0
  226. package/dist/react/react/hooks/useConfig.d.ts +9 -0
  227. package/dist/react/react/hooks/useConfig.d.ts.map +1 -0
  228. package/dist/react/react/hooks/useConfig.js +82 -0
  229. package/dist/react/react/hooks/useConfig.mjs +79 -0
  230. package/dist/react/react/hooks/useConsent.d.ts +13 -0
  231. package/dist/react/react/hooks/useConsent.d.ts.map +1 -0
  232. package/dist/react/react/hooks/useConsent.js +50 -0
  233. package/dist/react/react/hooks/useConsent.mjs +47 -0
  234. package/dist/react/react/hooks/useDataDeletion.d.ts +17 -0
  235. package/dist/react/react/hooks/useDataDeletion.d.ts.map +1 -0
  236. package/dist/react/react/hooks/useDataDeletion.js +83 -0
  237. package/dist/react/react/hooks/useDataDeletion.mjs +80 -0
  238. package/dist/react/react/hooks/useGrainAnalytics.d.ts +6 -0
  239. package/dist/react/react/hooks/useGrainAnalytics.d.ts.map +1 -0
  240. package/dist/react/react/hooks/useGrainAnalytics.js +16 -0
  241. package/dist/react/react/hooks/useGrainAnalytics.mjs +13 -0
  242. package/dist/react/react/hooks/usePrivacyPreferences.d.ts +15 -0
  243. package/dist/react/react/hooks/usePrivacyPreferences.d.ts.map +1 -0
  244. package/dist/react/react/hooks/usePrivacyPreferences.js +48 -0
  245. package/dist/react/react/hooks/usePrivacyPreferences.mjs +45 -0
  246. package/dist/react/react/hooks/useTrack.d.ts +9 -0
  247. package/dist/react/react/hooks/useTrack.d.ts.map +1 -0
  248. package/dist/react/react/hooks/useTrack.js +19 -0
  249. package/dist/react/react/hooks/useTrack.mjs +16 -0
  250. package/dist/react/react/index.d.ts +47 -0
  251. package/dist/react/react/index.d.ts.map +1 -0
  252. package/dist/react/react/index.js +58 -0
  253. package/dist/react/react/index.mjs +44 -0
  254. package/dist/react/react/types.d.ts +33 -0
  255. package/dist/react/react/types.d.ts.map +1 -0
  256. package/dist/react/react/types.js +5 -0
  257. package/dist/react/react/types.mjs +4 -0
  258. package/package.json +20 -2
@@ -0,0 +1,79 @@
1
+ /**
2
+ * useConfig - Cache-first config access with automatic background refresh
3
+ *
4
+ * Returns cached/default value immediately, fetches fresh data in background,
5
+ * and automatically updates when configuration changes.
6
+ */
7
+ import * as React from 'react';
8
+ import { useGrainAnalytics } from './useGrainAnalytics';
9
+ export function useConfig(key, options = {}) {
10
+ const client = useGrainAnalytics();
11
+ // Get initial value from cache/defaults (synchronous, instant)
12
+ const [value, setValue] = React.useState(() => client.getConfig(key));
13
+ const [isRefreshing, setIsRefreshing] = React.useState(false);
14
+ const [error, setError] = React.useState(null);
15
+ const isMountedRef = React.useRef(true);
16
+ // Fetch fresh config from API
17
+ const fetchConfig = React.useCallback(async () => {
18
+ if (!isMountedRef.current)
19
+ return;
20
+ setIsRefreshing(true);
21
+ setError(null);
22
+ try {
23
+ const response = await client.fetchConfig({
24
+ immediateKeys: options.immediateKeys || [key],
25
+ properties: options.properties,
26
+ forceRefresh: options.forceRefresh,
27
+ });
28
+ if (isMountedRef.current && response) {
29
+ const newValue = response.configurations[key];
30
+ if (newValue !== undefined) {
31
+ setValue(newValue);
32
+ }
33
+ }
34
+ }
35
+ catch (err) {
36
+ if (isMountedRef.current) {
37
+ setError(err instanceof Error ? err : new Error(String(err)));
38
+ }
39
+ }
40
+ finally {
41
+ if (isMountedRef.current) {
42
+ setIsRefreshing(false);
43
+ }
44
+ }
45
+ }, [client, key, options.immediateKeys, options.properties, options.forceRefresh]);
46
+ // Manual refresh function
47
+ const refresh = React.useCallback(async () => {
48
+ await fetchConfig();
49
+ }, [fetchConfig]);
50
+ // Background fetch on mount and when key/options change
51
+ React.useEffect(() => {
52
+ fetchConfig();
53
+ }, [fetchConfig]);
54
+ // Subscribe to config changes
55
+ React.useEffect(() => {
56
+ const listener = (configurations) => {
57
+ if (isMountedRef.current && configurations[key] !== undefined) {
58
+ setValue(configurations[key]);
59
+ }
60
+ };
61
+ client.addConfigChangeListener(listener);
62
+ return () => {
63
+ client.removeConfigChangeListener(listener);
64
+ };
65
+ }, [client, key]);
66
+ // Track mount state
67
+ React.useEffect(() => {
68
+ isMountedRef.current = true;
69
+ return () => {
70
+ isMountedRef.current = false;
71
+ };
72
+ }, []);
73
+ return {
74
+ value,
75
+ isRefreshing,
76
+ error,
77
+ refresh,
78
+ };
79
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * useConsent - Hook for managing user consent
3
+ */
4
+ import type { ConsentState } from '../../consent';
5
+ export declare function useConsent(): {
6
+ consentState: ConsentState;
7
+ grantConsent: (categories?: string[]) => void;
8
+ revokeConsent: (categories?: string[]) => void;
9
+ hasConsent: (category?: string) => boolean;
10
+ isGranted: boolean;
11
+ categories: string[];
12
+ };
13
+ //# sourceMappingURL=useConsent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useConsent.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks/useConsent.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,wBAAgB,UAAU;;gCAwBR,MAAM,EAAE;iCASR,MAAM,EAAE;4BASV,MAAM;;;EAerB"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * useConsent - Hook for managing user consent
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useConsent = useConsent;
7
+ const React = require("react");
8
+ const useGrainAnalytics_1 = require("./useGrainAnalytics");
9
+ function useConsent() {
10
+ const client = (0, useGrainAnalytics_1.useGrainAnalytics)();
11
+ const [consentState, setConsentState] = React.useState(null);
12
+ React.useEffect(() => {
13
+ if (!client)
14
+ return;
15
+ // Get initial consent state
16
+ const initialState = client.getConsentState();
17
+ setConsentState(initialState);
18
+ // Listen for consent changes
19
+ const listener = (state) => {
20
+ setConsentState(state);
21
+ };
22
+ client.onConsentChange(listener);
23
+ return () => {
24
+ client.offConsentChange(listener);
25
+ };
26
+ }, [client]);
27
+ const grantConsent = React.useCallback((categories) => {
28
+ if (client) {
29
+ client.grantConsent(categories);
30
+ }
31
+ }, [client]);
32
+ const revokeConsent = React.useCallback((categories) => {
33
+ if (client) {
34
+ client.revokeConsent(categories);
35
+ }
36
+ }, [client]);
37
+ const hasConsent = React.useCallback((category) => {
38
+ if (!client)
39
+ return false;
40
+ return client.hasConsent(category);
41
+ }, [client]);
42
+ return {
43
+ consentState,
44
+ grantConsent,
45
+ revokeConsent,
46
+ hasConsent,
47
+ isGranted: consentState?.granted ?? false,
48
+ categories: consentState?.categories ?? [],
49
+ };
50
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * useConsent - Hook for managing user consent
3
+ */
4
+ import * as React from 'react';
5
+ import { useGrainAnalytics } from './useGrainAnalytics';
6
+ export function useConsent() {
7
+ const client = useGrainAnalytics();
8
+ const [consentState, setConsentState] = React.useState(null);
9
+ React.useEffect(() => {
10
+ if (!client)
11
+ return;
12
+ // Get initial consent state
13
+ const initialState = client.getConsentState();
14
+ setConsentState(initialState);
15
+ // Listen for consent changes
16
+ const listener = (state) => {
17
+ setConsentState(state);
18
+ };
19
+ client.onConsentChange(listener);
20
+ return () => {
21
+ client.offConsentChange(listener);
22
+ };
23
+ }, [client]);
24
+ const grantConsent = React.useCallback((categories) => {
25
+ if (client) {
26
+ client.grantConsent(categories);
27
+ }
28
+ }, [client]);
29
+ const revokeConsent = React.useCallback((categories) => {
30
+ if (client) {
31
+ client.revokeConsent(categories);
32
+ }
33
+ }, [client]);
34
+ const hasConsent = React.useCallback((category) => {
35
+ if (!client)
36
+ return false;
37
+ return client.hasConsent(category);
38
+ }, [client]);
39
+ return {
40
+ consentState,
41
+ grantConsent,
42
+ revokeConsent,
43
+ hasConsent,
44
+ isGranted: consentState?.granted ?? false,
45
+ categories: consentState?.categories ?? [],
46
+ };
47
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * useDataDeletion - Hook for triggering data deletion requests
3
+ * This is a client-side utility - actual deletion happens on the server
4
+ */
5
+ export interface DataDeletionOptions {
6
+ apiUrl: string;
7
+ tenantId: string;
8
+ onSuccess?: (message: string) => void;
9
+ onError?: (error: string) => void;
10
+ }
11
+ export declare function useDataDeletion(options: DataDeletionOptions): {
12
+ requestDeletion: (userId: string) => Promise<any>;
13
+ requestAnonymization: (userId: string) => Promise<any>;
14
+ loading: boolean;
15
+ error: string;
16
+ };
17
+ //# sourceMappingURL=useDataDeletion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDataDeletion.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks/useDataDeletion.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB;8BAKzC,MAAM;mCAyCN,MAAM;;;EA6CxB"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /**
3
+ * useDataDeletion - Hook for triggering data deletion requests
4
+ * This is a client-side utility - actual deletion happens on the server
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.useDataDeletion = useDataDeletion;
8
+ const React = require("react");
9
+ function useDataDeletion(options) {
10
+ const [loading, setLoading] = React.useState(false);
11
+ const [error, setError] = React.useState(null);
12
+ const requestDeletion = React.useCallback(async (userId) => {
13
+ setLoading(true);
14
+ setError(null);
15
+ try {
16
+ const response = await fetch(`${options.apiUrl}/v1/privacy/${options.tenantId}/data-deletion`, {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ body: JSON.stringify({
22
+ userId,
23
+ deleteEvents: true,
24
+ deleteProperties: true,
25
+ deleteConsentAudit: false,
26
+ }),
27
+ });
28
+ if (!response.ok) {
29
+ throw new Error(`HTTP ${response.status}`);
30
+ }
31
+ const result = await response.json();
32
+ options.onSuccess?.(result.message);
33
+ return result;
34
+ }
35
+ catch (err) {
36
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
37
+ setError(errorMessage);
38
+ options.onError?.(errorMessage);
39
+ throw err;
40
+ }
41
+ finally {
42
+ setLoading(false);
43
+ }
44
+ }, [options]);
45
+ const requestAnonymization = React.useCallback(async (userId) => {
46
+ setLoading(true);
47
+ setError(null);
48
+ try {
49
+ const response = await fetch(`${options.apiUrl}/v1/privacy/${options.tenantId}/anonymize-user`, {
50
+ method: 'POST',
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ },
54
+ body: JSON.stringify({
55
+ userId,
56
+ anonymizeEvents: true,
57
+ anonymizeProperties: true,
58
+ }),
59
+ });
60
+ if (!response.ok) {
61
+ throw new Error(`HTTP ${response.status}`);
62
+ }
63
+ const result = await response.json();
64
+ options.onSuccess?.(result.message);
65
+ return result;
66
+ }
67
+ catch (err) {
68
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
69
+ setError(errorMessage);
70
+ options.onError?.(errorMessage);
71
+ throw err;
72
+ }
73
+ finally {
74
+ setLoading(false);
75
+ }
76
+ }, [options]);
77
+ return {
78
+ requestDeletion,
79
+ requestAnonymization,
80
+ loading,
81
+ error,
82
+ };
83
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * useDataDeletion - Hook for triggering data deletion requests
3
+ * This is a client-side utility - actual deletion happens on the server
4
+ */
5
+ import * as React from 'react';
6
+ export function useDataDeletion(options) {
7
+ const [loading, setLoading] = React.useState(false);
8
+ const [error, setError] = React.useState(null);
9
+ const requestDeletion = React.useCallback(async (userId) => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ const response = await fetch(`${options.apiUrl}/v1/privacy/${options.tenantId}/data-deletion`, {
14
+ method: 'POST',
15
+ headers: {
16
+ 'Content-Type': 'application/json',
17
+ },
18
+ body: JSON.stringify({
19
+ userId,
20
+ deleteEvents: true,
21
+ deleteProperties: true,
22
+ deleteConsentAudit: false,
23
+ }),
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`HTTP ${response.status}`);
27
+ }
28
+ const result = await response.json();
29
+ options.onSuccess?.(result.message);
30
+ return result;
31
+ }
32
+ catch (err) {
33
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
34
+ setError(errorMessage);
35
+ options.onError?.(errorMessage);
36
+ throw err;
37
+ }
38
+ finally {
39
+ setLoading(false);
40
+ }
41
+ }, [options]);
42
+ const requestAnonymization = React.useCallback(async (userId) => {
43
+ setLoading(true);
44
+ setError(null);
45
+ try {
46
+ const response = await fetch(`${options.apiUrl}/v1/privacy/${options.tenantId}/anonymize-user`, {
47
+ method: 'POST',
48
+ headers: {
49
+ 'Content-Type': 'application/json',
50
+ },
51
+ body: JSON.stringify({
52
+ userId,
53
+ anonymizeEvents: true,
54
+ anonymizeProperties: true,
55
+ }),
56
+ });
57
+ if (!response.ok) {
58
+ throw new Error(`HTTP ${response.status}`);
59
+ }
60
+ const result = await response.json();
61
+ options.onSuccess?.(result.message);
62
+ return result;
63
+ }
64
+ catch (err) {
65
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
66
+ setError(errorMessage);
67
+ options.onError?.(errorMessage);
68
+ throw err;
69
+ }
70
+ finally {
71
+ setLoading(false);
72
+ }
73
+ }, [options]);
74
+ return {
75
+ requestDeletion,
76
+ requestAnonymization,
77
+ loading,
78
+ error,
79
+ };
80
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * useGrainAnalytics - Access the GrainAnalytics client from context
3
+ */
4
+ import type { GrainAnalytics } from '../../index';
5
+ export declare function useGrainAnalytics(): GrainAnalytics;
6
+ //# sourceMappingURL=useGrainAnalytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGrainAnalytics.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks/useGrainAnalytics.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAgB,iBAAiB,IAAI,cAAc,CAWlD"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /**
3
+ * useGrainAnalytics - Access the GrainAnalytics client from context
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useGrainAnalytics = useGrainAnalytics;
7
+ const React = require("react");
8
+ const context_1 = require("../context");
9
+ function useGrainAnalytics() {
10
+ const context = React.useContext(context_1.GrainContext);
11
+ if (!context) {
12
+ throw new Error('useGrainAnalytics must be used within a GrainProvider. ' +
13
+ 'Wrap your component tree with <GrainProvider client={client}> or <GrainProvider config={{...}}>');
14
+ }
15
+ return context.client;
16
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * useGrainAnalytics - Access the GrainAnalytics client from context
3
+ */
4
+ import * as React from 'react';
5
+ import { GrainContext } from '../context';
6
+ export function useGrainAnalytics() {
7
+ const context = React.useContext(GrainContext);
8
+ if (!context) {
9
+ throw new Error('useGrainAnalytics must be used within a GrainProvider. ' +
10
+ 'Wrap your component tree with <GrainProvider client={client}> or <GrainProvider config={{...}}>');
11
+ }
12
+ return context.client;
13
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * usePrivacyPreferences - Hook for managing privacy preferences
3
+ */
4
+ export interface PrivacyPreferences {
5
+ necessary: boolean;
6
+ analytics: boolean;
7
+ functional: boolean;
8
+ }
9
+ export declare function usePrivacyPreferences(): {
10
+ preferences: PrivacyPreferences;
11
+ updatePreferences: (newPreferences: Partial<PrivacyPreferences>) => void;
12
+ acceptAll: () => void;
13
+ rejectAll: () => void;
14
+ };
15
+ //# sourceMappingURL=usePrivacyPreferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePrivacyPreferences.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks/usePrivacyPreferences.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,qBAAqB;;wCAahB,OAAO,CAAC,kBAAkB,CAAC;;;EAqC/C"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * usePrivacyPreferences - Hook for managing privacy preferences
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.usePrivacyPreferences = usePrivacyPreferences;
7
+ const React = require("react");
8
+ const useConsent_1 = require("./useConsent");
9
+ function usePrivacyPreferences() {
10
+ const { consentState, grantConsent, revokeConsent } = (0, useConsent_1.useConsent)();
11
+ const preferences = React.useMemo(() => {
12
+ const categories = consentState?.categories ?? [];
13
+ return {
14
+ necessary: categories.includes('necessary'),
15
+ analytics: categories.includes('analytics'),
16
+ functional: categories.includes('functional'),
17
+ };
18
+ }, [consentState]);
19
+ const updatePreferences = React.useCallback((newPreferences) => {
20
+ const categories = [];
21
+ // Necessary is always enabled
22
+ categories.push('necessary');
23
+ if (newPreferences.analytics ?? preferences.analytics) {
24
+ categories.push('analytics');
25
+ }
26
+ if (newPreferences.functional ?? preferences.functional) {
27
+ categories.push('functional');
28
+ }
29
+ if (categories.length > 0) {
30
+ grantConsent(categories);
31
+ }
32
+ else {
33
+ revokeConsent();
34
+ }
35
+ }, [preferences, grantConsent, revokeConsent]);
36
+ const acceptAll = React.useCallback(() => {
37
+ grantConsent(['necessary', 'analytics', 'functional']);
38
+ }, [grantConsent]);
39
+ const rejectAll = React.useCallback(() => {
40
+ grantConsent(['necessary']); // Keep only necessary
41
+ }, [grantConsent]);
42
+ return {
43
+ preferences,
44
+ updatePreferences,
45
+ acceptAll,
46
+ rejectAll,
47
+ };
48
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * usePrivacyPreferences - Hook for managing privacy preferences
3
+ */
4
+ import * as React from 'react';
5
+ import { useConsent } from './useConsent';
6
+ export function usePrivacyPreferences() {
7
+ const { consentState, grantConsent, revokeConsent } = useConsent();
8
+ const preferences = React.useMemo(() => {
9
+ const categories = consentState?.categories ?? [];
10
+ return {
11
+ necessary: categories.includes('necessary'),
12
+ analytics: categories.includes('analytics'),
13
+ functional: categories.includes('functional'),
14
+ };
15
+ }, [consentState]);
16
+ const updatePreferences = React.useCallback((newPreferences) => {
17
+ const categories = [];
18
+ // Necessary is always enabled
19
+ categories.push('necessary');
20
+ if (newPreferences.analytics ?? preferences.analytics) {
21
+ categories.push('analytics');
22
+ }
23
+ if (newPreferences.functional ?? preferences.functional) {
24
+ categories.push('functional');
25
+ }
26
+ if (categories.length > 0) {
27
+ grantConsent(categories);
28
+ }
29
+ else {
30
+ revokeConsent();
31
+ }
32
+ }, [preferences, grantConsent, revokeConsent]);
33
+ const acceptAll = React.useCallback(() => {
34
+ grantConsent(['necessary', 'analytics', 'functional']);
35
+ }, [grantConsent]);
36
+ const rejectAll = React.useCallback(() => {
37
+ grantConsent(['necessary']); // Keep only necessary
38
+ }, [grantConsent]);
39
+ return {
40
+ preferences,
41
+ updatePreferences,
42
+ acceptAll,
43
+ rejectAll,
44
+ };
45
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * useTrack - Get a stable, memoized track function
3
+ *
4
+ * Returns a track function that doesn't cause re-renders when passed to child components.
5
+ * Prevents unnecessary re-renders compared to using useCallback.
6
+ */
7
+ import type { TrackFunction } from '../types';
8
+ export declare function useTrack(): TrackFunction;
9
+ //# sourceMappingURL=useTrack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTrack.d.ts","sourceRoot":"","sources":["../../../../src/react/hooks/useTrack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,QAAQ,IAAI,aAAa,CAYxC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ /**
3
+ * useTrack - Get a stable, memoized track function
4
+ *
5
+ * Returns a track function that doesn't cause re-renders when passed to child components.
6
+ * Prevents unnecessary re-renders compared to using useCallback.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.useTrack = useTrack;
10
+ const React = require("react");
11
+ const useGrainAnalytics_1 = require("./useGrainAnalytics");
12
+ function useTrack() {
13
+ const client = (0, useGrainAnalytics_1.useGrainAnalytics)();
14
+ // Create stable track function that won't change across renders
15
+ const track = React.useCallback(async (eventName, properties, options) => {
16
+ await client.track(eventName, properties, options);
17
+ }, [client]);
18
+ return track;
19
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * useTrack - Get a stable, memoized track function
3
+ *
4
+ * Returns a track function that doesn't cause re-renders when passed to child components.
5
+ * Prevents unnecessary re-renders compared to using useCallback.
6
+ */
7
+ import * as React from 'react';
8
+ import { useGrainAnalytics } from './useGrainAnalytics';
9
+ export function useTrack() {
10
+ const client = useGrainAnalytics();
11
+ // Create stable track function that won't change across renders
12
+ const track = React.useCallback(async (eventName, properties, options) => {
13
+ await client.track(eventName, properties, options);
14
+ }, [client]);
15
+ return track;
16
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Grain Analytics React Hooks
3
+ *
4
+ * React integration for @grainql/analytics-web
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * import { GrainProvider, useConfig, useTrack } from '@grainql/analytics-web/react';
9
+ *
10
+ * // Pattern 1: Provider-managed client
11
+ * <GrainProvider config={{ tenantId: 'xxx' }}>
12
+ * <App />
13
+ * </GrainProvider>
14
+ *
15
+ * // Pattern 2: External client
16
+ * const grain = new GrainAnalytics({ tenantId: 'xxx' });
17
+ * <GrainProvider client={grain}>
18
+ * <App />
19
+ * </GrainProvider>
20
+ *
21
+ * // Use hooks in components
22
+ * function MyComponent() {
23
+ * const { value } = useConfig('hero_variant');
24
+ * const track = useTrack();
25
+ *
26
+ * return <button onClick={() => track('clicked')}>Click</button>;
27
+ * }
28
+ * ```
29
+ */
30
+ export { GrainProvider } from './GrainProvider';
31
+ export { useGrainAnalytics } from './hooks/useGrainAnalytics';
32
+ export { useConfig } from './hooks/useConfig';
33
+ export { useAllConfigs } from './hooks/useAllConfigs';
34
+ export { useTrack } from './hooks/useTrack';
35
+ export { useConsent } from './hooks/useConsent';
36
+ export { usePrivacyPreferences } from './hooks/usePrivacyPreferences';
37
+ export { useDataDeletion } from './hooks/useDataDeletion';
38
+ export { ConsentBanner } from './components/ConsentBanner';
39
+ export { PrivacyPreferenceCenter } from './components/PrivacyPreferenceCenter';
40
+ export { CookieNotice } from './components/CookieNotice';
41
+ export type { GrainProviderProps, UseConfigOptions, UseConfigResult, UseAllConfigsOptions, UseAllConfigsResult, TrackFunction, } from './types';
42
+ export type { ConsentBannerProps } from './components/ConsentBanner';
43
+ export type { PrivacyPreferenceCenterProps } from './components/PrivacyPreferenceCenter';
44
+ export type { CookieNoticeProps } from './components/CookieNotice';
45
+ export type { PrivacyPreferences } from './hooks/usePrivacyPreferences';
46
+ export type { DataDeletionOptions } from './hooks/useDataDeletion';
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,GACd,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,YAAY,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAC;AACzF,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}