c15t 0.0.1-rc.3

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 (86) hide show
  1. package/.turbo/turbo-build.log +54 -0
  2. package/.turbo/turbo-fmt.log +6 -0
  3. package/.turbo/turbo-lint.log +288 -0
  4. package/.turbo/turbo-test.log +33 -0
  5. package/CHANGELOG.md +20 -0
  6. package/LICENSE.md +595 -0
  7. package/README.md +28 -0
  8. package/dist/index.cjs +118 -0
  9. package/dist/index.d.ts +27 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +19 -0
  12. package/dist/libs/__tests__/tracking-blocker.test.cjs +269 -0
  13. package/dist/libs/__tests__/tracking-blocker.test.d.ts +2 -0
  14. package/dist/libs/__tests__/tracking-blocker.test.d.ts.map +1 -0
  15. package/dist/libs/__tests__/tracking-blocker.test.js +267 -0
  16. package/dist/libs/consent-utils.cjs +68 -0
  17. package/dist/libs/consent-utils.d.ts +49 -0
  18. package/dist/libs/consent-utils.d.ts.map +1 -0
  19. package/dist/libs/consent-utils.js +23 -0
  20. package/dist/libs/tracking-blocker.cjs +167 -0
  21. package/dist/libs/tracking-blocker.d.ts +33 -0
  22. package/dist/libs/tracking-blocker.d.ts.map +1 -0
  23. package/dist/libs/tracking-blocker.js +108 -0
  24. package/dist/libs/tracking-domains.cjs +188 -0
  25. package/dist/libs/tracking-domains.d.ts +7 -0
  26. package/dist/libs/tracking-domains.d.ts.map +1 -0
  27. package/dist/libs/tracking-domains.js +146 -0
  28. package/dist/store.cjs +248 -0
  29. package/dist/store.d.ts +58 -0
  30. package/dist/store.d.ts.map +1 -0
  31. package/dist/store.initial-state.cjs +105 -0
  32. package/dist/store.initial-state.d.ts +43 -0
  33. package/dist/store.initial-state.d.ts.map +1 -0
  34. package/dist/store.initial-state.js +66 -0
  35. package/dist/store.js +219 -0
  36. package/dist/store.type.cjs +22 -0
  37. package/dist/store.type.d.ts +159 -0
  38. package/dist/store.type.d.ts.map +1 -0
  39. package/dist/store.type.js +0 -0
  40. package/dist/translations/en.cjs +96 -0
  41. package/dist/translations/en.d.ts +3 -0
  42. package/dist/translations/en.d.ts.map +1 -0
  43. package/dist/translations/en.js +54 -0
  44. package/dist/translations/index.cjs +51 -0
  45. package/dist/translations/index.d.ts +3 -0
  46. package/dist/translations/index.d.ts.map +1 -0
  47. package/dist/translations/index.js +9 -0
  48. package/dist/types/callbacks.cjs +22 -0
  49. package/dist/types/callbacks.d.ts +146 -0
  50. package/dist/types/callbacks.d.ts.map +1 -0
  51. package/dist/types/callbacks.js +0 -0
  52. package/dist/types/compliance.cjs +22 -0
  53. package/dist/types/compliance.d.ts +196 -0
  54. package/dist/types/compliance.d.ts.map +1 -0
  55. package/dist/types/compliance.js +0 -0
  56. package/dist/types/gdpr.cjs +86 -0
  57. package/dist/types/gdpr.d.ts +168 -0
  58. package/dist/types/gdpr.d.ts.map +1 -0
  59. package/dist/types/gdpr.js +44 -0
  60. package/dist/types/index.cjs +44 -0
  61. package/dist/types/index.d.ts +141 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/types/index.js +4 -0
  64. package/dist/types/translations.cjs +22 -0
  65. package/dist/types/translations.d.ts +52 -0
  66. package/dist/types/translations.d.ts.map +1 -0
  67. package/dist/types/translations.js +0 -0
  68. package/package.json +33 -0
  69. package/rslib.config.ts +28 -0
  70. package/src/index.ts +31 -0
  71. package/src/libs/__tests__/tracking-blocker.test.ts +271 -0
  72. package/src/libs/consent-utils.ts +70 -0
  73. package/src/libs/tracking-blocker.ts +202 -0
  74. package/src/libs/tracking-domains.ts +158 -0
  75. package/src/store.initial-state.ts +123 -0
  76. package/src/store.ts +450 -0
  77. package/src/store.type.ts +187 -0
  78. package/src/translations/en.ts +55 -0
  79. package/src/translations/index.ts +10 -0
  80. package/src/types/callbacks.ts +152 -0
  81. package/src/types/compliance.ts +205 -0
  82. package/src/types/gdpr.ts +217 -0
  83. package/src/types/index.ts +148 -0
  84. package/src/types/translations.ts +60 -0
  85. package/tsconfig.json +12 -0
  86. package/vitest.config.ts +15 -0
@@ -0,0 +1,70 @@
1
+ import type { AllConsentNames, ConsentState } from '../types';
2
+
3
+ /**
4
+ * Determines the effective consents based on the user's Do Not Track setting.
5
+ *
6
+ * @param consents - The current state of user consents.
7
+ * @param honorDoNotTrack - Whether to respect the user's Do Not Track setting.
8
+ * @returns The effective consents after considering Do Not Track.
9
+ */
10
+ export function getEffectiveConsents(
11
+ consents: ConsentState,
12
+ honorDoNotTrack: boolean
13
+ ): ConsentState {
14
+ if (
15
+ honorDoNotTrack &&
16
+ typeof window !== 'undefined' &&
17
+ window.navigator.doNotTrack === '1'
18
+ ) {
19
+ return Object.keys(consents).reduce((acc, key) => {
20
+ if (key in consents) {
21
+ acc[key as AllConsentNames] = key === 'necessary';
22
+ }
23
+ return acc;
24
+ }, {} as ConsentState);
25
+ }
26
+ return consents;
27
+ }
28
+
29
+ /**
30
+ * Checks if the user has given consent for a specific type.
31
+ *
32
+ * @param consentType - The type of consent to check.
33
+ * @param consents - The current state of user consents.
34
+ * @param honorDoNotTrack - Whether to respect the user's Do Not Track setting.
35
+ * @returns True if consent is given, false otherwise.
36
+ */
37
+ export function hasConsentFor(
38
+ consentType: AllConsentNames,
39
+ consents: ConsentState,
40
+ honorDoNotTrack: boolean
41
+ ): boolean {
42
+ const effectiveConsents = getEffectiveConsents(consents, honorDoNotTrack);
43
+ return effectiveConsents[consentType] || false;
44
+ }
45
+
46
+ /**
47
+ * Determines if the user has consented based on consent information.
48
+ *
49
+ * @param consentInfo - The consent information.
50
+ * @returns True if the user has consented, false otherwise.
51
+ */
52
+ export function hasConsented(
53
+ consentInfo: { time: number; type: 'all' | 'custom' | 'necessary' } | null
54
+ ): boolean {
55
+ return consentInfo !== null;
56
+ }
57
+
58
+ /**
59
+ * Checks if a specific consent type is enabled.
60
+ *
61
+ * @param consentType - The type of consent to check.
62
+ * @param consents - The current state of user consents.
63
+ * @returns True if the consent type is enabled, false otherwise.
64
+ */
65
+ export function isConsentEnabled(
66
+ consentType: AllConsentNames,
67
+ consents: ConsentState
68
+ ): boolean {
69
+ return consents[consentType] || false;
70
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Implements automatic blocking of tracking scripts and network requests until user consent is granted.
4
+ *
5
+ * IMPORTANT: This module overrides global `fetch` and `XMLHttpRequest` APIs to enforce consent requirements.
6
+ * While this approach is necessary for proper consent management, it may conflict with other libraries that
7
+ * also modify these APIs. This implementation takes precedence to ensure compliance.
8
+ */
9
+
10
+ import type { AllConsentNames, ConsentState } from '../types';
11
+ import DEFAULT_DOMAIN_CONSENT_MAP from './tracking-domains';
12
+
13
+ /**
14
+ * Configuration options for the tracking blocker
15
+ */
16
+ export interface TrackingBlockerConfig {
17
+ /** Whether to disable automatic blocking (defaults to false) */
18
+ disableAutomaticBlocking?: boolean;
19
+
20
+ /** Override the default domain consent map */
21
+ overrideDomainConsentMap?: boolean;
22
+
23
+ /** Map of domains to their required consent types */
24
+ domainConsentMap?: Record<string, AllConsentNames>;
25
+ }
26
+
27
+ /**
28
+ * Create default consent state with all consents set to their default values
29
+ */
30
+ function createDefaultConsentState(): ConsentState {
31
+ return {
32
+ experience: false,
33
+ functionality: false,
34
+ marketing: false,
35
+ measurement: false,
36
+ necessary: true,
37
+ };
38
+ }
39
+
40
+ interface TrackingBlocker {
41
+ updateConsents: (newConsents: ConsentState) => void;
42
+ destroy: () => void;
43
+ }
44
+
45
+ /**
46
+ * Creates a tracking blocker instance that handles blocking of tracking scripts and network requests
47
+ */
48
+ export function createTrackingBlocker(
49
+ config: TrackingBlockerConfig = {},
50
+ initialConsents?: ConsentState
51
+ ): TrackingBlocker {
52
+ const blockerConfig = {
53
+ disableAutomaticBlocking: false,
54
+ ...config,
55
+ domainConsentMap: config.overrideDomainConsentMap
56
+ ? config.domainConsentMap
57
+ : { ...DEFAULT_DOMAIN_CONSENT_MAP, ...config.domainConsentMap },
58
+ };
59
+
60
+ let consents = initialConsents || createDefaultConsentState();
61
+ const originalFetch = window.fetch;
62
+ const originalXHR = window.XMLHttpRequest;
63
+
64
+ /**
65
+ * Normalize a domain by removing 'www.' prefix and ensuring consistent format
66
+ */
67
+ function normalizeDomain(domain: string): string {
68
+ return domain
69
+ .toLowerCase()
70
+ .replace(/^www\./, '')
71
+ .replace(/:\d+$/, '') // Remove port numbers
72
+ .trim();
73
+ }
74
+
75
+ /**
76
+ * Check if a domain matches any entry in the domain map, including subdomains
77
+ */
78
+ function findMatchingDomain(
79
+ domain: string,
80
+ domainMap: Record<string, AllConsentNames>
81
+ ): AllConsentNames | undefined {
82
+ const normalizedDomain = normalizeDomain(domain);
83
+
84
+ // First try exact match
85
+ const directMatch = domainMap[normalizedDomain];
86
+ if (directMatch) {
87
+ return directMatch;
88
+ }
89
+
90
+ // Then try matching as a subdomain
91
+ for (const [mapDomain, consent] of Object.entries(domainMap)) {
92
+ const normalizedMapDomain = normalizeDomain(mapDomain);
93
+ if (
94
+ normalizedDomain.endsWith(`.${normalizedMapDomain}`) ||
95
+ normalizedDomain === normalizedMapDomain
96
+ ) {
97
+ return consent;
98
+ }
99
+ }
100
+
101
+ return undefined;
102
+ }
103
+
104
+ /**
105
+ * Check if a URL requires consent and if that consent has been granted
106
+ */
107
+ function isRequestAllowed(url: string): boolean {
108
+ try {
109
+ const domain = new URL(url).hostname;
110
+ const requiredConsent = findMatchingDomain(
111
+ domain,
112
+ blockerConfig.domainConsentMap || {}
113
+ );
114
+
115
+ if (!requiredConsent) {
116
+ return true;
117
+ }
118
+
119
+ const isAllowed = consents[requiredConsent] === true;
120
+ return isAllowed;
121
+ } catch (error) {
122
+ return true;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Dispatch an event when a request is blocked due to missing consent
128
+ */
129
+ function dispatchConsentBlockedEvent(url: string): void {
130
+ document.dispatchEvent(
131
+ new CustomEvent('ConsentBlockedRequest', { detail: { url } })
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Intercept and potentially block network requests
137
+ */
138
+ function interceptNetworkRequests(): void {
139
+ // Override fetch only if it hasn't been modified by another script
140
+ if (window.fetch === originalFetch) {
141
+ window.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
142
+ const url = input instanceof Request ? input.url : input.toString();
143
+ if (!isRequestAllowed(url)) {
144
+ dispatchConsentBlockedEvent(url);
145
+ return Promise.reject(
146
+ new Error(`Request to ${url} blocked due to missing consent`)
147
+ );
148
+ }
149
+
150
+ return await originalFetch.call(window, input, init);
151
+ };
152
+ }
153
+
154
+ // Override XMLHttpRequest only if it hasn't been modified
155
+ if (window.XMLHttpRequest === originalXHR) {
156
+ window.XMLHttpRequest = class extends originalXHR {
157
+ override open(
158
+ method: string,
159
+ url: string | URL,
160
+ async = true,
161
+ username?: string,
162
+ password?: string
163
+ ) {
164
+ if (!isRequestAllowed(url.toString())) {
165
+ dispatchConsentBlockedEvent(url.toString());
166
+ throw new Error(`Request to ${url} blocked due to missing consent`);
167
+ }
168
+
169
+ super.open(method, url, async, username, password);
170
+ }
171
+ };
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Safe restoration of fetch and XHR
177
+ */
178
+ function restoreOriginalRequests(): void {
179
+ // Restore fetch if it has been overridden
180
+ if (window.fetch !== originalFetch) {
181
+ window.fetch = originalFetch;
182
+ }
183
+
184
+ if (window.XMLHttpRequest !== originalXHR) {
185
+ window.XMLHttpRequest = originalXHR;
186
+ }
187
+ }
188
+
189
+ // Initialize if automatic blocking is enabled
190
+ if (!blockerConfig.disableAutomaticBlocking) {
191
+ interceptNetworkRequests();
192
+ }
193
+
194
+ return {
195
+ updateConsents: (newConsents: ConsentState) => {
196
+ consents = newConsents;
197
+ },
198
+ destroy: () => {
199
+ restoreOriginalRequests();
200
+ },
201
+ };
202
+ }
@@ -0,0 +1,158 @@
1
+ import type { AllConsentNames } from '../types';
2
+
3
+ /**
4
+ * Default tracking domains that require specific consent types
5
+ */
6
+ const DEFAULT_DOMAIN_CONSENT_MAP: Record<string, AllConsentNames> = {
7
+ // Analytics/Measurement domains
8
+ 'www.google-analytics.com': 'measurement',
9
+ 'analytics.google.com': 'measurement',
10
+ 'www.googletagmanager.com': 'measurement',
11
+ 'stats.g.doubleclick.net': 'measurement',
12
+ 'ampcid.google.com': 'measurement',
13
+ 'analytics.twitter.com': 'measurement',
14
+ 'analytics.pinterest.com': 'measurement',
15
+ 'dc.services.visualstudio.com': 'measurement',
16
+ 'www.clarity.ms': 'measurement',
17
+ 'www.hotjar.com': 'measurement',
18
+ 'static.hotjar.com': 'measurement',
19
+ 'script.hotjar.com': 'measurement',
20
+ 'insights.hotjar.com': 'measurement',
21
+ 'mouseflow.com': 'measurement',
22
+ 'api.mouseflow.com': 'measurement',
23
+ 'tools.mouseflow.com': 'measurement',
24
+ 'cdn.heapanalytics.com': 'measurement',
25
+ 'plausible.io': 'measurement',
26
+ 'matomo.cloud': 'measurement',
27
+ 'matomo.org': 'measurement',
28
+ 'mixpanel.com': 'measurement',
29
+ 'api.mixpanel.com': 'measurement',
30
+ 'sentry.io': 'measurement',
31
+ 'browser.sentry-cdn.com': 'measurement',
32
+ 'js.monitor.azure.com': 'measurement',
33
+ 'stats.wp.com': 'measurement',
34
+ 'pixel.wp.com': 'measurement',
35
+ 'analytics.amplitude.com': 'measurement',
36
+ 'api2.amplitude.com': 'measurement',
37
+ 'cdn.amplitude.com': 'measurement',
38
+ 'api.segment.io': 'measurement',
39
+ 'cdn.segment.com': 'measurement',
40
+ 'api.segment.com': 'measurement',
41
+ 'pendo.io': 'measurement',
42
+ 'data.pendo.io': 'measurement',
43
+ 'cdn.pendo.io': 'measurement',
44
+
45
+ // Marketing/Advertising domains
46
+ 'connect.facebook.net': 'marketing',
47
+ 'platform.twitter.com': 'marketing',
48
+ 'platform.linkedin.com': 'marketing',
49
+ 'www.googleadservices.com': 'marketing',
50
+ 'doubleclick.net': 'marketing',
51
+ 'googleads.g.doubleclick.net': 'marketing',
52
+ 'ad.doubleclick.net': 'marketing',
53
+ 'www.facebook.com': 'marketing',
54
+ 'ads.linkedin.com': 'marketing',
55
+ 'ads-api.tiktok.com': 'marketing',
56
+ 'analytics.tiktok.com': 'marketing',
57
+ 'business.tiktok.com': 'marketing',
58
+ 'ads.pinterest.com': 'marketing',
59
+ 'log.pinterest.com': 'marketing',
60
+ 'ads-twitter.com': 'marketing',
61
+ 'static.ads-twitter.com': 'marketing',
62
+ 'advertising.twitter.com': 'marketing',
63
+ 'ads.yahoo.com': 'marketing',
64
+ 'sp.analytics.yahoo.com': 'marketing',
65
+ 'gemini.yahoo.com': 'marketing',
66
+ 'adroll.com': 'marketing',
67
+ 'a.adroll.com': 'marketing',
68
+ 'd.adroll.com': 'marketing',
69
+ 's.adroll.com': 'marketing',
70
+ 'adform.net': 'marketing',
71
+ 'track.adform.net': 'marketing',
72
+ 'dmp.adform.net': 'marketing',
73
+ 'criteo.com': 'marketing',
74
+ 'static.criteo.net': 'marketing',
75
+ 'bidder.criteo.com': 'marketing',
76
+ 'dynamic.criteo.com': 'marketing',
77
+ 'gum.criteo.com': 'marketing',
78
+ 'taboola.com': 'marketing',
79
+ 'cdn.taboola.com': 'marketing',
80
+ 'trc.taboola.com': 'marketing',
81
+ 'outbrain.com': 'marketing',
82
+ 'widgets.outbrain.com': 'marketing',
83
+ 'tr.outbrain.com': 'marketing',
84
+ 'amplify.outbrain.com': 'marketing',
85
+ 'bing.com': 'marketing',
86
+ 'bat.bing.com': 'marketing',
87
+ 'clarity.ms': 'marketing',
88
+ 'quantserve.com': 'marketing',
89
+ 'secure.quantserve.com': 'marketing',
90
+ 'pixel.quantserve.com': 'marketing',
91
+ 'exelator.com': 'marketing',
92
+ 'load.exelator.com': 'marketing',
93
+ 'api.exelator.com': 'marketing',
94
+ 'ad.360yield.com': 'marketing',
95
+ 'match.360yield.com': 'marketing',
96
+ 'ad.turn.com': 'marketing',
97
+ 'r.turn.com': 'marketing',
98
+ 'd.turn.com': 'marketing',
99
+
100
+ // Functionality domains
101
+ 'cdn.jsdelivr.net': 'functionality',
102
+ 'ajax.googleapis.com': 'functionality',
103
+ 'fonts.googleapis.com': 'functionality',
104
+ 'maps.googleapis.com': 'functionality',
105
+ 'www.recaptcha.net': 'functionality',
106
+ 'recaptcha.net': 'functionality',
107
+ 'www.gstatic.com': 'functionality',
108
+ 'fonts.gstatic.com': 'functionality',
109
+ 'cdnjs.cloudflare.com': 'functionality',
110
+ 'unpkg.com': 'functionality',
111
+ 'code.jquery.com': 'functionality',
112
+ 'maxcdn.bootstrapcdn.com': 'functionality',
113
+ 'cdn.datatables.net': 'functionality',
114
+ 'js.stripe.com': 'functionality',
115
+ 'api.stripe.com': 'functionality',
116
+ 'checkout.stripe.com': 'functionality',
117
+ 'js.braintreegateway.com': 'functionality',
118
+ 'api.braintreegateway.com': 'functionality',
119
+ 'cdn.shopify.com': 'functionality',
120
+ 'js.intercomcdn.com': 'functionality',
121
+ 'widget.intercom.io': 'functionality',
122
+ 'cdn.auth0.com': 'functionality',
123
+ 'js.pusher.com': 'functionality',
124
+ 'sockjs.pusher.com': 'functionality',
125
+
126
+ // Experience/UX domains
127
+ 'app.optimizely.com': 'experience',
128
+ 'cdn.optimizely.com': 'experience',
129
+ 'logx.optimizely.com': 'experience',
130
+ 'cdn.mouseflow.com': 'experience',
131
+ 'fullstory.com': 'experience',
132
+ 'rs.fullstory.com': 'experience',
133
+ 'edge.fullstory.com': 'experience',
134
+ 'vwo.com': 'experience',
135
+ 'dev.visualwebsiteoptimizer.com': 'experience',
136
+ 'assets.adobedtm.com': 'experience',
137
+ 'cdn.tt.omtrdc.net': 'experience',
138
+ 'demdex.net': 'experience',
139
+ 'sc.omtrdc.net': 'experience',
140
+ 'crazyegg.com': 'experience',
141
+ 'script.crazyegg.com': 'experience',
142
+ 'tracking.crazyegg.com': 'experience',
143
+ 'luckyorange.com': 'experience',
144
+ 'cdn.luckyorange.com': 'experience',
145
+ 'w1.luckyorange.com': 'experience',
146
+ 'upload.luckyorange.com': 'experience',
147
+ 'clicktale.net': 'experience',
148
+ 'cdn.clicktale.net': 'experience',
149
+ 'conductor.clicktale.net': 'experience',
150
+ 'userzoom.com': 'experience',
151
+ 'cdn.userzoom.com': 'experience',
152
+ 'api.userzoom.com': 'experience',
153
+ 'contentsquare.net': 'experience',
154
+ 't.contentsquare.net': 'experience',
155
+ 'app.contentsquare.com': 'experience',
156
+ };
157
+
158
+ export default DEFAULT_DOMAIN_CONSENT_MAP;
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Provides the default initial state configuration for the consent management store.
4
+ */
5
+
6
+ import type { PrivacyConsentState } from './store.type';
7
+ import { defaultTranslationConfig } from './translations';
8
+ import { type ConsentState, consentTypes } from './types';
9
+
10
+ /**
11
+ * Default initial state for the consent management store.
12
+ *
13
+ * @remarks
14
+ * This configuration establishes the baseline state for the consent manager,
15
+ * including default consent values, compliance settings, and privacy preferences.
16
+ *
17
+ * Notable defaults include:
18
+ * - All consents start with their type-specific default values
19
+ * - GDPR compliance is globally enabled
20
+ * - CCPA compliance is enabled for US users only
21
+ * - Do Not Track is respected by default
22
+ * - Only necessary and marketing consents are included in gdprTypes
23
+ *
24
+ * @example
25
+ * Using the initial state:
26
+ * ```typescript
27
+ * const store = createConsentManagerStore();
28
+ *
29
+ * // Reset to initial state
30
+ * store.setState(initialState);
31
+ *
32
+ * // Extend initial state
33
+ * const customState = {
34
+ * ...initialState,
35
+ * privacySettings: {
36
+ * honorDoNotTrack: false
37
+ * }
38
+ * };
39
+ * ```
40
+ *
41
+ * @public
42
+ */
43
+ export const initialState: Omit<
44
+ PrivacyConsentState,
45
+ 'getEffectiveConsents' | 'hasConsentFor'
46
+ > = {
47
+ /** Initial consent states based on default values from consent types */
48
+ consents: consentTypes.reduce((acc, consent) => {
49
+ acc[consent.name] = consent.defaultValue;
50
+ return acc;
51
+ }, {} as ConsentState),
52
+
53
+ /** No consent information stored initially */
54
+ consentInfo: null,
55
+
56
+ /** Show consent popup by default */
57
+ showPopup: true,
58
+
59
+ /** Default GDPR consent types to include */
60
+ gdprTypes: ['necessary', 'marketing'],
61
+
62
+ /** Privacy dialog starts closed */
63
+ isPrivacyDialogOpen: false,
64
+
65
+ /** Default compliance settings per region */
66
+ complianceSettings: {
67
+ /** GDPR: Enabled globally by default */
68
+ gdpr: { enabled: true, appliesGlobally: true, applies: true },
69
+
70
+ /** CCPA: Enabled for US only */
71
+ ccpa: { enabled: true, appliesGlobally: false, applies: undefined },
72
+
73
+ /** LGPD: Disabled by default */
74
+ lgpd: { enabled: false, appliesGlobally: false, applies: undefined },
75
+
76
+ /** US State Privacy: Enabled for US only */
77
+ usStatePrivacy: {
78
+ enabled: true,
79
+ appliesGlobally: false,
80
+ applies: undefined,
81
+ },
82
+ },
83
+
84
+ /** Empty callbacks object - should be populated by implementation */
85
+ callbacks: {},
86
+
87
+ /** Default to US if no country detected */
88
+ detectedCountry: 'US',
89
+
90
+ /** Default privacy settings */
91
+ privacySettings: {
92
+ /** Respect Do Not Track by default */
93
+ honorDoNotTrack: true,
94
+ },
95
+
96
+ /** Default translation configuration */
97
+ translationConfig: defaultTranslationConfig,
98
+
99
+ /** Don't include non-displayed consents by default */
100
+ includeNonDisplayedConsents: false,
101
+
102
+ /** Use predefined consent types */
103
+ consentTypes: consentTypes,
104
+
105
+ // Initialize all methods as no-ops
106
+ setConsent: () => {},
107
+ setShowPopup: () => {},
108
+ setIsPrivacyDialogOpen: () => {},
109
+ saveConsents: () => {},
110
+ resetConsents: () => {},
111
+ setGdprTypes: () => {},
112
+ setComplianceSetting: () => {},
113
+ resetComplianceSettings: () => {},
114
+ setCallback: () => {},
115
+ setDetectedCountry: () => {},
116
+ getDisplayedConsents: () => [],
117
+ hasConsented: () => false,
118
+ setTranslationConfig: () => {},
119
+ clearAllData: () => {},
120
+ updateConsentMode: () => {},
121
+ setPrivacySettings: () => {},
122
+ setIncludeNonDisplayedConsents: () => {},
123
+ };