@react-lgpd-consent/core 0.7.0 → 0.7.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.
- package/CHANGELOG.md +205 -0
- package/README.md +16 -1
- package/dist/index.cjs +602 -154
- package/dist/index.d.cts +167 -13
- package/dist/index.d.ts +167 -13
- package/dist/index.js +598 -155
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -309,6 +309,7 @@ function setDebugLogging(enabled, level = 2 /* INFO */) {
|
|
|
309
309
|
// src/utils/cookieUtils.ts
|
|
310
310
|
var DEFAULT_STORAGE_NAMESPACE = "lgpd-consent";
|
|
311
311
|
var DEFAULT_STORAGE_VERSION = "1";
|
|
312
|
+
var DEFAULT_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;
|
|
312
313
|
function buildConsentStorageKey(options) {
|
|
313
314
|
const namespaceRaw = options?.namespace?.trim() || DEFAULT_STORAGE_NAMESPACE;
|
|
314
315
|
const versionRaw = options?.version?.trim() || DEFAULT_STORAGE_VERSION;
|
|
@@ -318,12 +319,31 @@ function buildConsentStorageKey(options) {
|
|
|
318
319
|
}
|
|
319
320
|
var DEFAULT_COOKIE_OPTS = {
|
|
320
321
|
name: "cookieConsent",
|
|
322
|
+
maxAge: DEFAULT_MAX_AGE_SECONDS,
|
|
321
323
|
maxAgeDays: 365,
|
|
322
324
|
sameSite: "Lax",
|
|
323
325
|
secure: globalThis.window === void 0 ? false : globalThis.window.location.protocol === "https:",
|
|
324
326
|
path: "/",
|
|
325
327
|
domain: void 0
|
|
326
328
|
};
|
|
329
|
+
function resolveCookieOptions(opts) {
|
|
330
|
+
const protocols = [
|
|
331
|
+
typeof globalThis.window !== "undefined" ? globalThis.window?.location?.protocol : void 0,
|
|
332
|
+
typeof globalThis.location !== "undefined" ? globalThis.location?.protocol : void 0
|
|
333
|
+
].filter(Boolean);
|
|
334
|
+
const forceHttps = globalThis.__LGPD_FORCE_HTTPS__ === true;
|
|
335
|
+
const isHttps = forceHttps || protocols.includes("https:");
|
|
336
|
+
const maxAgeSecondsFromDays = typeof opts?.maxAgeDays === "number" ? Math.max(0, opts.maxAgeDays * 24 * 60 * 60) : null;
|
|
337
|
+
const maxAgeSeconds = typeof opts?.maxAge === "number" ? Math.max(0, opts.maxAge) : maxAgeSecondsFromDays ?? DEFAULT_MAX_AGE_SECONDS;
|
|
338
|
+
return {
|
|
339
|
+
name: opts?.name ?? DEFAULT_COOKIE_OPTS.name,
|
|
340
|
+
maxAge: maxAgeSeconds,
|
|
341
|
+
sameSite: opts?.sameSite ?? DEFAULT_COOKIE_OPTS.sameSite ?? "Lax",
|
|
342
|
+
secure: typeof opts?.secure === "boolean" ? opts.secure : isHttps ? true : DEFAULT_COOKIE_OPTS.secure ?? false,
|
|
343
|
+
path: opts?.path ?? DEFAULT_COOKIE_OPTS.path ?? "/",
|
|
344
|
+
domain: opts?.domain ?? DEFAULT_COOKIE_OPTS.domain ?? void 0
|
|
345
|
+
};
|
|
346
|
+
}
|
|
327
347
|
var COOKIE_SCHEMA_VERSION = "1.0";
|
|
328
348
|
function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
|
|
329
349
|
logger.debug("Reading consent cookie", { name });
|
|
@@ -339,6 +359,10 @@ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
|
|
|
339
359
|
try {
|
|
340
360
|
const data = JSON.parse(raw);
|
|
341
361
|
logger.cookieOperation("read", name, data);
|
|
362
|
+
if (!data || typeof data !== "object") {
|
|
363
|
+
logger.warn("Consent cookie malformed: payload is not an object");
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
342
366
|
if (!data.version) {
|
|
343
367
|
logger.debug("Migrating legacy cookie format");
|
|
344
368
|
return migrateLegacyCookie(data);
|
|
@@ -347,7 +371,11 @@ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
|
|
|
347
371
|
logger.warn(`Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`);
|
|
348
372
|
return null;
|
|
349
373
|
}
|
|
350
|
-
|
|
374
|
+
const preferences = data && typeof data.preferences === "object" ? data.preferences : { necessary: true };
|
|
375
|
+
return {
|
|
376
|
+
...data,
|
|
377
|
+
preferences: ensureNecessaryAlwaysOn(preferences)
|
|
378
|
+
};
|
|
351
379
|
} catch (error) {
|
|
352
380
|
logger.error("Error parsing consent cookie", error);
|
|
353
381
|
return null;
|
|
@@ -370,12 +398,12 @@ function migrateLegacyCookie(legacyData) {
|
|
|
370
398
|
}
|
|
371
399
|
}
|
|
372
400
|
function writeConsentCookie(state, config, opts, source = "banner") {
|
|
373
|
-
if (typeof document === "undefined") {
|
|
401
|
+
if (typeof document === "undefined" || typeof window === "undefined" || globalThis.__LGPD_SSR__ === true) {
|
|
374
402
|
logger.debug("Cookie write skipped: server-side environment");
|
|
375
403
|
return;
|
|
376
404
|
}
|
|
377
405
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
378
|
-
const o =
|
|
406
|
+
const o = resolveCookieOptions(opts);
|
|
379
407
|
const preferences = ensureNecessaryAlwaysOn(state.preferences);
|
|
380
408
|
const cookieData = {
|
|
381
409
|
version: COOKIE_SCHEMA_VERSION,
|
|
@@ -387,8 +415,9 @@ function writeConsentCookie(state, config, opts, source = "banner") {
|
|
|
387
415
|
projectConfig: config
|
|
388
416
|
};
|
|
389
417
|
logger.cookieOperation("write", o.name, cookieData);
|
|
418
|
+
const expires = new Date(Date.now() + o.maxAge * 1e3);
|
|
390
419
|
Cookies.set(o.name, JSON.stringify(cookieData), {
|
|
391
|
-
expires
|
|
420
|
+
expires,
|
|
392
421
|
sameSite: o.sameSite,
|
|
393
422
|
secure: o.secure,
|
|
394
423
|
path: o.path,
|
|
@@ -422,14 +451,14 @@ function removeConsentCookie(opts) {
|
|
|
422
451
|
logger.debug("Cookie removal skipped: server-side environment");
|
|
423
452
|
return;
|
|
424
453
|
}
|
|
425
|
-
const o =
|
|
454
|
+
const o = resolveCookieOptions(opts);
|
|
426
455
|
logger.cookieOperation("delete", o.name);
|
|
427
456
|
Cookies.remove(o.name, { path: o.path, domain: o.domain });
|
|
428
457
|
logger.info("Consent cookie removed");
|
|
429
458
|
}
|
|
430
459
|
|
|
431
460
|
// src/utils/dataLayerEvents.ts
|
|
432
|
-
var LIBRARY_VERSION = "0.7.
|
|
461
|
+
var LIBRARY_VERSION = "0.7.1";
|
|
433
462
|
function ensureDataLayer() {
|
|
434
463
|
var _a;
|
|
435
464
|
if (globalThis.window === void 0) return;
|
|
@@ -442,7 +471,8 @@ function pushConsentInitializedEvent(categories) {
|
|
|
442
471
|
event: "consent_initialized",
|
|
443
472
|
consent_version: LIBRARY_VERSION,
|
|
444
473
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
445
|
-
categories
|
|
474
|
+
categories,
|
|
475
|
+
preferences: categories
|
|
446
476
|
};
|
|
447
477
|
globalThis.window.dataLayer?.push(event);
|
|
448
478
|
}
|
|
@@ -456,6 +486,7 @@ function pushConsentUpdatedEvent(categories, origin, previousCategories) {
|
|
|
456
486
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
457
487
|
origin,
|
|
458
488
|
categories,
|
|
489
|
+
preferences: categories,
|
|
459
490
|
changed_categories: changedCategories
|
|
460
491
|
};
|
|
461
492
|
globalThis.window.dataLayer?.push(event);
|
|
@@ -1065,58 +1096,8 @@ var GUIDANCE_PRESETS = {
|
|
|
1065
1096
|
};
|
|
1066
1097
|
|
|
1067
1098
|
// src/utils/peerDepsCheck.ts
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
try {
|
|
1071
|
-
const reactSymbols = Object.getOwnPropertySymbols(globalThis.window).map(String).filter((name) => name.includes("react"));
|
|
1072
|
-
if (reactSymbols.length > 1) {
|
|
1073
|
-
return true;
|
|
1074
|
-
}
|
|
1075
|
-
const ReactModule = window.React;
|
|
1076
|
-
if (ReactModule && Array.isArray(ReactModule)) {
|
|
1077
|
-
return true;
|
|
1078
|
-
}
|
|
1079
|
-
const hasMultipleVersions = window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers?.size > 1;
|
|
1080
|
-
return hasMultipleVersions || false;
|
|
1081
|
-
} catch {
|
|
1082
|
-
return false;
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
function getPackageVersion(packageName) {
|
|
1086
|
-
if (globalThis.window === void 0) return null;
|
|
1087
|
-
try {
|
|
1088
|
-
const pkg = window[packageName];
|
|
1089
|
-
if (pkg?.version) return pkg.version;
|
|
1090
|
-
const React6 = window.React;
|
|
1091
|
-
if (packageName === "react" && React6?.version) {
|
|
1092
|
-
return React6.version;
|
|
1093
|
-
}
|
|
1094
|
-
return null;
|
|
1095
|
-
} catch {
|
|
1096
|
-
return null;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
function isVersionInRange(version, minMajor, maxMajor) {
|
|
1100
|
-
const major = Number.parseInt(version.split(".")[0], 10);
|
|
1101
|
-
return major >= minMajor && major <= maxMajor;
|
|
1102
|
-
}
|
|
1103
|
-
function checkPeerDeps(options = {}) {
|
|
1104
|
-
const { skipInProduction = true, logWarnings = true } = options;
|
|
1105
|
-
const result = {
|
|
1106
|
-
ok: true,
|
|
1107
|
-
warnings: [],
|
|
1108
|
-
errors: []
|
|
1109
|
-
};
|
|
1110
|
-
const isProduction = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
|
|
1111
|
-
if (skipInProduction && isProduction) {
|
|
1112
|
-
return result;
|
|
1113
|
-
}
|
|
1114
|
-
if (globalThis.window === void 0) {
|
|
1115
|
-
return result;
|
|
1116
|
-
}
|
|
1117
|
-
if (detectMultipleReactInstances()) {
|
|
1118
|
-
result.ok = false;
|
|
1119
|
-
const errorMsg = `
|
|
1099
|
+
var MESSAGES_PT_BR = {
|
|
1100
|
+
MULTIPLE_REACT_INSTANCES: `
|
|
1120
1101
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1121
1102
|
\u2551 \u26A0\uFE0F ERRO: M\xFAltiplas inst\xE2ncias de React detectadas \u2551
|
|
1122
1103
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
@@ -1178,22 +1159,13 @@ function checkPeerDeps(options = {}) {
|
|
|
1178
1159
|
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#multiple-react-instances
|
|
1179
1160
|
|
|
1180
1161
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
if (logWarnings) {
|
|
1184
|
-
console.error(errorMsg);
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
const reactVersion = getPackageVersion("react");
|
|
1188
|
-
if (reactVersion) {
|
|
1189
|
-
if (!isVersionInRange(reactVersion, 18, 19)) {
|
|
1190
|
-
result.ok = false;
|
|
1191
|
-
const errorMsg = `
|
|
1162
|
+
`,
|
|
1163
|
+
UNSUPPORTED_REACT_VERSION: (version) => `
|
|
1192
1164
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1193
1165
|
\u2551 \u26A0\uFE0F AVISO: Vers\xE3o do React n\xE3o suportada \u2551
|
|
1194
1166
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1195
1167
|
|
|
1196
|
-
\u{1F4E6} Vers\xE3o detectada: React ${
|
|
1168
|
+
\u{1F4E6} Vers\xE3o detectada: React ${version}
|
|
1197
1169
|
\u2705 Vers\xF5es suportadas: React 18.x ou 19.x
|
|
1198
1170
|
|
|
1199
1171
|
\u{1F50D} O react-lgpd-consent requer React 18.2.0+ ou React 19.x
|
|
@@ -1211,27 +1183,13 @@ function checkPeerDeps(options = {}) {
|
|
|
1211
1183
|
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#react-version
|
|
1212
1184
|
|
|
1213
1185
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
if (logWarnings) {
|
|
1217
|
-
console.error(errorMsg);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
const muiVersion = window["@mui/material"]?.version;
|
|
1222
|
-
if (muiVersion) {
|
|
1223
|
-
if (!isVersionInRange(muiVersion, 5, 7)) {
|
|
1224
|
-
result.warnings.push(
|
|
1225
|
-
`MUI vers\xE3o ${muiVersion} detectada. Vers\xF5es suportadas: 5.15.0+, 6.x ou 7.x. Alguns componentes podem n\xE3o funcionar corretamente.`
|
|
1226
|
-
);
|
|
1227
|
-
if (logWarnings) {
|
|
1228
|
-
logger.warn(
|
|
1229
|
-
`
|
|
1186
|
+
`,
|
|
1187
|
+
UNSUPPORTED_MUI_VERSION: (version) => `
|
|
1230
1188
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1231
1189
|
\u2551 \u26A0\uFE0F AVISO: Vers\xE3o do Material-UI fora do range recomendado \u2551
|
|
1232
1190
|
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1233
1191
|
|
|
1234
|
-
\u{1F4E6} Vers\xE3o detectada: @mui/material ${
|
|
1192
|
+
\u{1F4E6} Vers\xE3o detectada: @mui/material ${version}
|
|
1235
1193
|
\u2705 Vers\xF5es suportadas: 5.15.0+, 6.x, 7.x
|
|
1236
1194
|
|
|
1237
1195
|
\u{1F50D} Componentes de UI (@react-lgpd-consent/mui) podem apresentar problemas.
|
|
@@ -1249,8 +1207,227 @@ function checkPeerDeps(options = {}) {
|
|
|
1249
1207
|
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#mui-version
|
|
1250
1208
|
|
|
1251
1209
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1252
|
-
|
|
1253
|
-
|
|
1210
|
+
`,
|
|
1211
|
+
MUI_OUT_OF_RANGE: (version) => `MUI vers\xE3o ${version} detectada. Vers\xF5es suportadas: 5.15.0+, 6.x ou 7.x. Alguns componentes podem n\xE3o funcionar corretamente.`
|
|
1212
|
+
};
|
|
1213
|
+
var MESSAGES_EN = {
|
|
1214
|
+
MULTIPLE_REACT_INSTANCES: `
|
|
1215
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1216
|
+
\u2551 \u26A0\uFE0F ERROR: Multiple React instances detected \u2551
|
|
1217
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1218
|
+
|
|
1219
|
+
\u{1F534} Problem:
|
|
1220
|
+
Your project is loading more than one copy of React, causing the error:
|
|
1221
|
+
"Invalid hook call. Hooks can only be called inside of the body of a
|
|
1222
|
+
function component."
|
|
1223
|
+
|
|
1224
|
+
\u{1F50D} Probable cause:
|
|
1225
|
+
\u2022 pnpm/Yarn PnP without proper peer dependency hoisting
|
|
1226
|
+
\u2022 node_modules with duplicate React (classic npm/yarn)
|
|
1227
|
+
\u2022 Webpack/Vite with multiple resolutions of the same package
|
|
1228
|
+
|
|
1229
|
+
\u2705 Solutions:
|
|
1230
|
+
|
|
1231
|
+
\u{1F4E6} PNPM (RECOMMENDED):
|
|
1232
|
+
Add to root package.json:
|
|
1233
|
+
{
|
|
1234
|
+
"pnpm": {
|
|
1235
|
+
"overrides": {
|
|
1236
|
+
"react": "$react",
|
|
1237
|
+
"react-dom": "$react-dom"
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
Run: pnpm install
|
|
1242
|
+
|
|
1243
|
+
\u{1F4E6} NPM/Yarn:
|
|
1244
|
+
Add to root package.json:
|
|
1245
|
+
{
|
|
1246
|
+
"overrides": {
|
|
1247
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
1248
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
Run: npm install (or yarn install)
|
|
1252
|
+
|
|
1253
|
+
\u{1F527} Webpack:
|
|
1254
|
+
Add to webpack.config.js:
|
|
1255
|
+
module.exports = {
|
|
1256
|
+
resolve: {
|
|
1257
|
+
alias: {
|
|
1258
|
+
react: path.resolve('./node_modules/react'),
|
|
1259
|
+
'react-dom': path.resolve('./node_modules/react-dom'),
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
\u26A1 Vite:
|
|
1265
|
+
Add to vite.config.js:
|
|
1266
|
+
export default {
|
|
1267
|
+
resolve: {
|
|
1268
|
+
dedupe: ['react', 'react-dom']
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
\u{1F4DA} Documentation:
|
|
1273
|
+
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#multiple-react-instances
|
|
1274
|
+
|
|
1275
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1276
|
+
`,
|
|
1277
|
+
UNSUPPORTED_REACT_VERSION: (version) => `
|
|
1278
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1279
|
+
\u2551 \u26A0\uFE0F WARNING: Unsupported React version \u2551
|
|
1280
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1281
|
+
|
|
1282
|
+
\u{1F4E6} Detected version: React ${version}
|
|
1283
|
+
\u2705 Supported versions: React 18.x or 19.x
|
|
1284
|
+
|
|
1285
|
+
\u{1F50D} react-lgpd-consent requires React 18.2.0+ or React 19.x
|
|
1286
|
+
|
|
1287
|
+
\u2705 Solution:
|
|
1288
|
+
Update React to a supported version:
|
|
1289
|
+
|
|
1290
|
+
npm install react@^18.2.0 react-dom@^18.2.0
|
|
1291
|
+
|
|
1292
|
+
or
|
|
1293
|
+
|
|
1294
|
+
npm install react@^19.0.0 react-dom@^19.0.0
|
|
1295
|
+
|
|
1296
|
+
\u{1F4DA} Documentation:
|
|
1297
|
+
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#react-version
|
|
1298
|
+
|
|
1299
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1300
|
+
`,
|
|
1301
|
+
UNSUPPORTED_MUI_VERSION: (version) => `
|
|
1302
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
1303
|
+
\u2551 \u26A0\uFE0F WARNING: Material-UI version out of recommended range \u2551
|
|
1304
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
1305
|
+
|
|
1306
|
+
\u{1F4E6} Detected version: @mui/material ${version}
|
|
1307
|
+
\u2705 Supported versions: 5.15.0+, 6.x, 7.x
|
|
1308
|
+
|
|
1309
|
+
\u{1F50D} UI components (@react-lgpd-consent/mui) may have issues.
|
|
1310
|
+
|
|
1311
|
+
\u2705 Solution:
|
|
1312
|
+
Update MUI to a supported version:
|
|
1313
|
+
|
|
1314
|
+
npm install @mui/material@^7.0.0 @emotion/react @emotion/styled
|
|
1315
|
+
|
|
1316
|
+
or keep 5.15.0+:
|
|
1317
|
+
|
|
1318
|
+
npm install @mui/material@^5.15.0 @emotion/react @emotion/styled
|
|
1319
|
+
|
|
1320
|
+
\u{1F4DA} Documentation:
|
|
1321
|
+
https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#mui-version
|
|
1322
|
+
|
|
1323
|
+
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1324
|
+
`,
|
|
1325
|
+
MUI_OUT_OF_RANGE: (version) => `MUI version ${version} detected. Supported versions: 5.15.0+, 6.x or 7.x. Some components may not work properly.`
|
|
1326
|
+
};
|
|
1327
|
+
var MESSAGES_BY_LOCALE = {
|
|
1328
|
+
"pt-BR": MESSAGES_PT_BR,
|
|
1329
|
+
en: MESSAGES_EN
|
|
1330
|
+
};
|
|
1331
|
+
var currentLocale = "pt-BR";
|
|
1332
|
+
var customMessages = {};
|
|
1333
|
+
function setPeerDepsLocale(locale) {
|
|
1334
|
+
currentLocale = locale;
|
|
1335
|
+
}
|
|
1336
|
+
function getPeerDepsLocale() {
|
|
1337
|
+
return currentLocale;
|
|
1338
|
+
}
|
|
1339
|
+
function setPeerDepsMessages(messages) {
|
|
1340
|
+
customMessages = { ...customMessages, ...messages };
|
|
1341
|
+
}
|
|
1342
|
+
function resetPeerDepsMessages() {
|
|
1343
|
+
customMessages = {};
|
|
1344
|
+
}
|
|
1345
|
+
function getMessages() {
|
|
1346
|
+
const baseMessages = MESSAGES_BY_LOCALE[currentLocale];
|
|
1347
|
+
if (Object.keys(customMessages).length === 0) {
|
|
1348
|
+
return baseMessages;
|
|
1349
|
+
}
|
|
1350
|
+
return {
|
|
1351
|
+
MULTIPLE_REACT_INSTANCES: customMessages.MULTIPLE_REACT_INSTANCES ?? baseMessages.MULTIPLE_REACT_INSTANCES,
|
|
1352
|
+
UNSUPPORTED_REACT_VERSION: customMessages.UNSUPPORTED_REACT_VERSION ?? baseMessages.UNSUPPORTED_REACT_VERSION,
|
|
1353
|
+
UNSUPPORTED_MUI_VERSION: customMessages.UNSUPPORTED_MUI_VERSION ?? baseMessages.UNSUPPORTED_MUI_VERSION,
|
|
1354
|
+
MUI_OUT_OF_RANGE: customMessages.MUI_OUT_OF_RANGE ?? baseMessages.MUI_OUT_OF_RANGE
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
function detectMultipleReactInstances() {
|
|
1358
|
+
if (globalThis.window === void 0) return false;
|
|
1359
|
+
try {
|
|
1360
|
+
const reactSymbols = Object.getOwnPropertySymbols(globalThis.window).map(String).filter((name) => name.includes("react"));
|
|
1361
|
+
if (reactSymbols.length > 1) {
|
|
1362
|
+
return true;
|
|
1363
|
+
}
|
|
1364
|
+
const ReactModule = window.React;
|
|
1365
|
+
if (ReactModule && Array.isArray(ReactModule)) {
|
|
1366
|
+
return true;
|
|
1367
|
+
}
|
|
1368
|
+
const hasMultipleVersions = window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers?.size > 1;
|
|
1369
|
+
return hasMultipleVersions || false;
|
|
1370
|
+
} catch {
|
|
1371
|
+
return false;
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
function getPackageVersion(packageName) {
|
|
1375
|
+
if (globalThis.window === void 0) return null;
|
|
1376
|
+
try {
|
|
1377
|
+
const pkg = window[packageName];
|
|
1378
|
+
if (pkg?.version) return pkg.version;
|
|
1379
|
+
const React6 = window.React;
|
|
1380
|
+
if (packageName === "react" && React6?.version) {
|
|
1381
|
+
return React6.version;
|
|
1382
|
+
}
|
|
1383
|
+
return null;
|
|
1384
|
+
} catch {
|
|
1385
|
+
return null;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
function isVersionInRange(version, minMajor, maxMajor) {
|
|
1389
|
+
const major = Number.parseInt(version.split(".")[0], 10);
|
|
1390
|
+
return major >= minMajor && major <= maxMajor;
|
|
1391
|
+
}
|
|
1392
|
+
function checkPeerDeps(options = {}) {
|
|
1393
|
+
const { skipInProduction = true, logWarnings = true } = options;
|
|
1394
|
+
const result = {
|
|
1395
|
+
ok: true,
|
|
1396
|
+
warnings: [],
|
|
1397
|
+
errors: []
|
|
1398
|
+
};
|
|
1399
|
+
const isProduction = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
|
|
1400
|
+
if (skipInProduction && isProduction) {
|
|
1401
|
+
return result;
|
|
1402
|
+
}
|
|
1403
|
+
if (globalThis.window === void 0) {
|
|
1404
|
+
return result;
|
|
1405
|
+
}
|
|
1406
|
+
const messages = getMessages();
|
|
1407
|
+
if (detectMultipleReactInstances()) {
|
|
1408
|
+
result.ok = false;
|
|
1409
|
+
result.errors.push(messages.MULTIPLE_REACT_INSTANCES);
|
|
1410
|
+
if (logWarnings) {
|
|
1411
|
+
console.error(messages.MULTIPLE_REACT_INSTANCES);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
const reactVersion = getPackageVersion("react");
|
|
1415
|
+
if (reactVersion) {
|
|
1416
|
+
if (!isVersionInRange(reactVersion, 18, 19)) {
|
|
1417
|
+
result.ok = false;
|
|
1418
|
+
const errorMsg = messages.UNSUPPORTED_REACT_VERSION(reactVersion);
|
|
1419
|
+
result.errors.push(errorMsg);
|
|
1420
|
+
if (logWarnings) {
|
|
1421
|
+
console.error(errorMsg);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
const muiVersion = window["@mui/material"]?.version;
|
|
1426
|
+
if (muiVersion) {
|
|
1427
|
+
if (!isVersionInRange(muiVersion, 5, 7)) {
|
|
1428
|
+
result.warnings.push(messages.MUI_OUT_OF_RANGE(muiVersion));
|
|
1429
|
+
if (logWarnings) {
|
|
1430
|
+
logger.warn(messages.UNSUPPORTED_MUI_VERSION(muiVersion));
|
|
1254
1431
|
}
|
|
1255
1432
|
}
|
|
1256
1433
|
}
|
|
@@ -1706,6 +1883,13 @@ function ConsentProvider({
|
|
|
1706
1883
|
return base;
|
|
1707
1884
|
}, [cookieOpts, storage?.domain, storage?.namespace, storage?.version]);
|
|
1708
1885
|
const consentVersion = storage?.version?.trim() || "1";
|
|
1886
|
+
React4.useEffect(() => {
|
|
1887
|
+
try {
|
|
1888
|
+
;
|
|
1889
|
+
globalThis.__LGPD_CONSENT_COOKIE__ = cookie.name;
|
|
1890
|
+
} catch {
|
|
1891
|
+
}
|
|
1892
|
+
}, [cookie.name]);
|
|
1709
1893
|
const finalCategoriesConfig = React4.useMemo(() => {
|
|
1710
1894
|
const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
|
|
1711
1895
|
if (!categories) return DEFAULT_PROJECT_CATEGORIES;
|
|
@@ -2068,51 +2252,99 @@ function ConsentGate(props) {
|
|
|
2068
2252
|
|
|
2069
2253
|
// src/utils/scriptLoader.ts
|
|
2070
2254
|
var LOADING_SCRIPTS = /* @__PURE__ */ new Map();
|
|
2071
|
-
|
|
2255
|
+
var DEFAULT_POLL_INTERVAL = 100;
|
|
2256
|
+
function resolveCookieNames(preferred) {
|
|
2257
|
+
const inferred = globalThis.__LGPD_CONSENT_COOKIE__ ?? null;
|
|
2258
|
+
const names = [preferred, inferred, "cookieConsent", "lgpd-consent__v1"].filter(
|
|
2259
|
+
Boolean
|
|
2260
|
+
);
|
|
2261
|
+
return Array.from(new Set(names));
|
|
2262
|
+
}
|
|
2263
|
+
function parseConsentFromCookie(names) {
|
|
2264
|
+
const raw = document.cookie;
|
|
2265
|
+
if (!raw) return null;
|
|
2266
|
+
const cookies = raw.split("; ").reduce((acc, part) => {
|
|
2267
|
+
const [k, ...rest] = part.split("=");
|
|
2268
|
+
acc[k] = rest.join("=");
|
|
2269
|
+
return acc;
|
|
2270
|
+
}, {});
|
|
2271
|
+
for (const name of names) {
|
|
2272
|
+
const value = cookies[name];
|
|
2273
|
+
if (!value) continue;
|
|
2274
|
+
try {
|
|
2275
|
+
const parsed = JSON.parse(decodeURIComponent(value));
|
|
2276
|
+
if (!parsed.consented || parsed.isModalOpen) continue;
|
|
2277
|
+
return parsed;
|
|
2278
|
+
} catch {
|
|
2279
|
+
continue;
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
return null;
|
|
2283
|
+
}
|
|
2284
|
+
function hasCategoryConsent(snapshot, category) {
|
|
2285
|
+
if (!snapshot.consented || snapshot.isModalOpen) return false;
|
|
2286
|
+
if (category === null) return true;
|
|
2287
|
+
return Boolean(snapshot.preferences?.[category]);
|
|
2288
|
+
}
|
|
2289
|
+
function loadScript(id, src, category = null, attrs = {}, nonce, options) {
|
|
2072
2290
|
if (typeof document === "undefined") return Promise.resolve();
|
|
2073
2291
|
if (document.getElementById(id)) return Promise.resolve();
|
|
2074
2292
|
const existingPromise = LOADING_SCRIPTS.get(id);
|
|
2075
2293
|
if (existingPromise) return existingPromise;
|
|
2294
|
+
const pollInterval = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL;
|
|
2295
|
+
const names = resolveCookieNames(options?.cookieName);
|
|
2296
|
+
const mergedAttrs = { ...attrs };
|
|
2076
2297
|
const promise = new Promise((resolve, reject) => {
|
|
2298
|
+
const inject = () => {
|
|
2299
|
+
const s = document.createElement("script");
|
|
2300
|
+
s.id = id;
|
|
2301
|
+
s.src = src;
|
|
2302
|
+
s.async = mergedAttrs.async !== "false";
|
|
2303
|
+
const scriptNonce = mergedAttrs.nonce || nonce;
|
|
2304
|
+
if (scriptNonce) {
|
|
2305
|
+
s.nonce = scriptNonce;
|
|
2306
|
+
mergedAttrs.nonce = scriptNonce;
|
|
2307
|
+
}
|
|
2308
|
+
for (const [k, v] of Object.entries(mergedAttrs)) s.setAttribute(k, v);
|
|
2309
|
+
s.onload = () => {
|
|
2310
|
+
LOADING_SCRIPTS.delete(id);
|
|
2311
|
+
resolve();
|
|
2312
|
+
};
|
|
2313
|
+
s.onerror = () => {
|
|
2314
|
+
LOADING_SCRIPTS.delete(id);
|
|
2315
|
+
reject(new Error(`Failed to load script: ${src}`));
|
|
2316
|
+
};
|
|
2317
|
+
document.body.appendChild(s);
|
|
2318
|
+
};
|
|
2319
|
+
const snapshot = options?.consentSnapshot;
|
|
2320
|
+
const skipChecks = options?.skipConsentCheck === true;
|
|
2321
|
+
if (skipChecks) {
|
|
2322
|
+
inject();
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
if (snapshot) {
|
|
2326
|
+
if (!hasCategoryConsent(snapshot, category)) {
|
|
2327
|
+
reject(
|
|
2328
|
+
new Error(
|
|
2329
|
+
`Consent not granted for category '${category ?? "none"}' when attempting to load ${id}`
|
|
2330
|
+
)
|
|
2331
|
+
);
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2334
|
+
inject();
|
|
2335
|
+
return;
|
|
2336
|
+
}
|
|
2077
2337
|
const checkConsent = () => {
|
|
2078
|
-
const
|
|
2079
|
-
if (!
|
|
2080
|
-
setTimeout(checkConsent,
|
|
2338
|
+
const consent = parseConsentFromCookie(names);
|
|
2339
|
+
if (!consent) {
|
|
2340
|
+
setTimeout(checkConsent, pollInterval);
|
|
2081
2341
|
return;
|
|
2082
2342
|
}
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
setTimeout(checkConsent, 100);
|
|
2087
|
-
return;
|
|
2088
|
-
}
|
|
2089
|
-
if (category && !consent.preferences[category]) {
|
|
2090
|
-
setTimeout(checkConsent, 100);
|
|
2091
|
-
return;
|
|
2092
|
-
}
|
|
2093
|
-
const s = document.createElement("script");
|
|
2094
|
-
s.id = id;
|
|
2095
|
-
s.src = src;
|
|
2096
|
-
s.async = true;
|
|
2097
|
-
const mergedAttrs = { ...attrs };
|
|
2098
|
-
const scriptNonce = mergedAttrs.nonce || nonce;
|
|
2099
|
-
if (scriptNonce) {
|
|
2100
|
-
s.nonce = scriptNonce;
|
|
2101
|
-
mergedAttrs.nonce = scriptNonce;
|
|
2102
|
-
}
|
|
2103
|
-
for (const [k, v] of Object.entries(mergedAttrs)) s.setAttribute(k, v);
|
|
2104
|
-
s.onload = () => {
|
|
2105
|
-
LOADING_SCRIPTS.delete(id);
|
|
2106
|
-
resolve();
|
|
2107
|
-
};
|
|
2108
|
-
s.onerror = () => {
|
|
2109
|
-
LOADING_SCRIPTS.delete(id);
|
|
2110
|
-
reject(new Error(`Failed to load script: ${src}`));
|
|
2111
|
-
};
|
|
2112
|
-
document.body.appendChild(s);
|
|
2113
|
-
} catch {
|
|
2114
|
-
setTimeout(checkConsent, 100);
|
|
2343
|
+
if (!hasCategoryConsent(consent, category)) {
|
|
2344
|
+
setTimeout(checkConsent, pollInterval);
|
|
2345
|
+
return;
|
|
2115
2346
|
}
|
|
2347
|
+
inject();
|
|
2116
2348
|
};
|
|
2117
2349
|
checkConsent();
|
|
2118
2350
|
});
|
|
@@ -2276,14 +2508,107 @@ function validateNecessaryClassification(integrations, enabledCategories) {
|
|
|
2276
2508
|
}
|
|
2277
2509
|
|
|
2278
2510
|
// src/utils/ConsentScriptLoader.tsx
|
|
2511
|
+
var scriptRegistry = /* @__PURE__ */ new Map();
|
|
2512
|
+
var queueListeners = /* @__PURE__ */ new Set();
|
|
2513
|
+
function notifyQueue() {
|
|
2514
|
+
queueListeners.forEach((listener) => {
|
|
2515
|
+
try {
|
|
2516
|
+
listener();
|
|
2517
|
+
} catch {
|
|
2518
|
+
}
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
function subscribeQueue(listener) {
|
|
2522
|
+
queueListeners.add(listener);
|
|
2523
|
+
return () => {
|
|
2524
|
+
queueListeners.delete(listener);
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2527
|
+
function createInternalScript(def) {
|
|
2528
|
+
return {
|
|
2529
|
+
...def,
|
|
2530
|
+
status: "pending",
|
|
2531
|
+
lastAllowed: false,
|
|
2532
|
+
registeredAt: Date.now(),
|
|
2533
|
+
token: Date.now() + Math.random(),
|
|
2534
|
+
priority: def.priority ?? 0,
|
|
2535
|
+
allowReload: def.allowReload ?? false,
|
|
2536
|
+
onConsentUpdate: def.onConsentUpdate
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
function registerScript(def) {
|
|
2540
|
+
const entry = createInternalScript(def);
|
|
2541
|
+
scriptRegistry.set(def.id, entry);
|
|
2542
|
+
notifyQueue();
|
|
2543
|
+
return () => {
|
|
2544
|
+
const current = scriptRegistry.get(def.id);
|
|
2545
|
+
if (current && current.token === entry.token) {
|
|
2546
|
+
scriptRegistry.delete(def.id);
|
|
2547
|
+
notifyQueue();
|
|
2548
|
+
}
|
|
2549
|
+
};
|
|
2550
|
+
}
|
|
2551
|
+
function getExecutableScripts(consent) {
|
|
2552
|
+
const allowedScripts = [];
|
|
2553
|
+
scriptRegistry.forEach((script) => {
|
|
2554
|
+
const categoryAllowed = script.category === "necessary" || consent.consented && Boolean(consent.preferences?.[script.category]);
|
|
2555
|
+
if (!categoryAllowed) {
|
|
2556
|
+
script.lastAllowed = false;
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
if (script.status === "running") return;
|
|
2560
|
+
if (script.status === "executed" && !script.allowReload) return;
|
|
2561
|
+
if (script.status === "executed" && script.allowReload && script.lastAllowed) return;
|
|
2562
|
+
script.lastAllowed = true;
|
|
2563
|
+
allowedScripts.push(script);
|
|
2564
|
+
});
|
|
2565
|
+
return allowedScripts.sort((a, b) => {
|
|
2566
|
+
if (a.category === "necessary" && b.category !== "necessary") return -1;
|
|
2567
|
+
if (b.category === "necessary" && a.category !== "necessary") return 1;
|
|
2568
|
+
if (a.category !== b.category) return a.category.localeCompare(b.category);
|
|
2569
|
+
if (a.priority !== b.priority) return (b.priority ?? 0) - (a.priority ?? 0);
|
|
2570
|
+
return a.registeredAt - b.registeredAt;
|
|
2571
|
+
});
|
|
2572
|
+
}
|
|
2573
|
+
async function processQueue(consent, devLogging) {
|
|
2574
|
+
const scripts = getExecutableScripts(consent);
|
|
2575
|
+
let order = 0;
|
|
2576
|
+
for (const script of scripts) {
|
|
2577
|
+
order += 1;
|
|
2578
|
+
script.status = "running";
|
|
2579
|
+
if (devLogging) {
|
|
2580
|
+
logger.info("[ConsentScriptLoader] executando script", {
|
|
2581
|
+
id: script.id,
|
|
2582
|
+
category: script.category,
|
|
2583
|
+
priority: script.priority ?? 0,
|
|
2584
|
+
order
|
|
2585
|
+
});
|
|
2586
|
+
}
|
|
2587
|
+
try {
|
|
2588
|
+
await Promise.resolve(script.execute());
|
|
2589
|
+
} catch (error) {
|
|
2590
|
+
logger.error(`\u274C Failed to execute script ${script.id}`, error);
|
|
2591
|
+
} finally {
|
|
2592
|
+
script.status = "executed";
|
|
2593
|
+
if (script.onConsentUpdate) {
|
|
2594
|
+
script.onConsentUpdate(consent);
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2279
2599
|
function ConsentScriptLoader({
|
|
2280
2600
|
integrations,
|
|
2281
2601
|
reloadOnChange = false,
|
|
2282
2602
|
nonce
|
|
2283
2603
|
}) {
|
|
2284
2604
|
const { preferences, consented } = useConsent();
|
|
2605
|
+
const isHydrated = useConsentHydration();
|
|
2285
2606
|
const categories = useCategories();
|
|
2286
|
-
const
|
|
2607
|
+
const [queueVersion, bumpQueueVersion] = React4.useState(0);
|
|
2608
|
+
React4.useEffect(() => {
|
|
2609
|
+
const unsubscribe = subscribeQueue(() => bumpQueueVersion((v) => v + 1));
|
|
2610
|
+
return unsubscribe;
|
|
2611
|
+
}, []);
|
|
2287
2612
|
React4.useEffect(() => {
|
|
2288
2613
|
try {
|
|
2289
2614
|
const ids = (integrations || []).map((i) => i.id);
|
|
@@ -2344,15 +2669,44 @@ function ConsentScriptLoader({
|
|
|
2344
2669
|
console.groupEnd();
|
|
2345
2670
|
}
|
|
2346
2671
|
}, [integrations, categories]);
|
|
2672
|
+
const processedIntegrationsRef = React4.useRef(/* @__PURE__ */ new Map());
|
|
2347
2673
|
React4.useEffect(() => {
|
|
2348
|
-
|
|
2349
|
-
const
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2674
|
+
const cleanups = [];
|
|
2675
|
+
const currentIds = /* @__PURE__ */ new Set();
|
|
2676
|
+
integrations.forEach((integration) => {
|
|
2677
|
+
currentIds.add(integration.id);
|
|
2678
|
+
const structuralHash = JSON.stringify({
|
|
2679
|
+
category: integration.category,
|
|
2680
|
+
src: integration.src,
|
|
2681
|
+
priority: integration.priority,
|
|
2682
|
+
hasBootstrap: Boolean(integration.bootstrap),
|
|
2683
|
+
hasInit: Boolean(integration.init),
|
|
2684
|
+
hasOnConsentUpdate: Boolean(integration.onConsentUpdate)
|
|
2685
|
+
});
|
|
2686
|
+
const existingHash = processedIntegrationsRef.current.get(integration.id);
|
|
2687
|
+
if (existingHash === structuralHash && scriptRegistry.has(integration.id)) {
|
|
2688
|
+
return;
|
|
2689
|
+
}
|
|
2690
|
+
processedIntegrationsRef.current.set(integration.id, structuralHash);
|
|
2691
|
+
if (integration.bootstrap) {
|
|
2692
|
+
cleanups.push(
|
|
2693
|
+
registerScript({
|
|
2694
|
+
id: `${integration.id}__bootstrap`,
|
|
2695
|
+
category: "necessary",
|
|
2696
|
+
priority: (integration.priority ?? 0) + 1e3,
|
|
2697
|
+
execute: integration.bootstrap
|
|
2698
|
+
})
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
cleanups.push(
|
|
2702
|
+
registerScript({
|
|
2703
|
+
id: integration.id,
|
|
2704
|
+
category: integration.category,
|
|
2705
|
+
priority: integration.priority,
|
|
2706
|
+
allowReload: reloadOnChange,
|
|
2707
|
+
onConsentUpdate: integration.onConsentUpdate,
|
|
2708
|
+
execute: async () => {
|
|
2709
|
+
const mergedAttrs = integration.attrs ? { ...integration.attrs } : {};
|
|
2356
2710
|
const scriptNonce = integration.nonce ?? nonce;
|
|
2357
2711
|
if (scriptNonce && !mergedAttrs.nonce) mergedAttrs.nonce = scriptNonce;
|
|
2358
2712
|
await loadScript(
|
|
@@ -2360,26 +2714,54 @@ function ConsentScriptLoader({
|
|
|
2360
2714
|
integration.src,
|
|
2361
2715
|
integration.category,
|
|
2362
2716
|
mergedAttrs,
|
|
2363
|
-
scriptNonce
|
|
2717
|
+
scriptNonce,
|
|
2718
|
+
{ skipConsentCheck: true }
|
|
2364
2719
|
);
|
|
2365
2720
|
if (integration.init) {
|
|
2366
2721
|
integration.init();
|
|
2367
2722
|
}
|
|
2368
|
-
loadedScripts.current.add(integration.id);
|
|
2369
|
-
} catch (error) {
|
|
2370
|
-
logger.error(`\u274C Failed to load script: ${integration.id}`, error);
|
|
2371
2723
|
}
|
|
2724
|
+
})
|
|
2725
|
+
);
|
|
2726
|
+
});
|
|
2727
|
+
processedIntegrationsRef.current.forEach((_, id) => {
|
|
2728
|
+
if (!currentIds.has(id)) {
|
|
2729
|
+
processedIntegrationsRef.current.delete(id);
|
|
2730
|
+
const script = scriptRegistry.get(id);
|
|
2731
|
+
if (script) {
|
|
2732
|
+
scriptRegistry.delete(id);
|
|
2733
|
+
}
|
|
2734
|
+
const bootstrapScript = scriptRegistry.get(`${id}__bootstrap`);
|
|
2735
|
+
if (bootstrapScript) {
|
|
2736
|
+
scriptRegistry.delete(`${id}__bootstrap`);
|
|
2372
2737
|
}
|
|
2373
2738
|
}
|
|
2374
|
-
}
|
|
2375
|
-
return () =>
|
|
2376
|
-
}, [
|
|
2739
|
+
});
|
|
2740
|
+
return () => cleanups.forEach((fn) => fn());
|
|
2741
|
+
}, [integrations, reloadOnChange, nonce]);
|
|
2742
|
+
React4.useEffect(() => {
|
|
2743
|
+
if (!isHydrated) return;
|
|
2744
|
+
void processQueue({ consented, preferences }, process.env.NODE_ENV !== "production");
|
|
2745
|
+
}, [consented, preferences, isHydrated, queueVersion]);
|
|
2746
|
+
React4.useEffect(() => {
|
|
2747
|
+
if (!isHydrated) return;
|
|
2748
|
+
scriptRegistry.forEach((script) => {
|
|
2749
|
+
if (script.status !== "executed") return;
|
|
2750
|
+
if (typeof script.onConsentUpdate !== "function") return;
|
|
2751
|
+
script.onConsentUpdate({ consented, preferences });
|
|
2752
|
+
});
|
|
2753
|
+
}, [consented, preferences, isHydrated]);
|
|
2377
2754
|
return null;
|
|
2378
2755
|
}
|
|
2379
2756
|
function useConsentScriptLoader() {
|
|
2380
2757
|
const { preferences, consented } = useConsent();
|
|
2758
|
+
const isHydrated = useConsentHydration();
|
|
2381
2759
|
return React4.useCallback(
|
|
2382
2760
|
async (integration, nonce) => {
|
|
2761
|
+
if (!isHydrated) {
|
|
2762
|
+
logger.warn(`\u26A0\uFE0F Cannot load script ${integration.id}: Consent not hydrated yet`);
|
|
2763
|
+
return false;
|
|
2764
|
+
}
|
|
2383
2765
|
if (!consented) {
|
|
2384
2766
|
logger.warn(`\u26A0\uFE0F Cannot load script ${integration.id}: No consent given`);
|
|
2385
2767
|
return false;
|
|
@@ -2400,7 +2782,11 @@ function useConsentScriptLoader() {
|
|
|
2400
2782
|
integration.src,
|
|
2401
2783
|
integration.category,
|
|
2402
2784
|
mergedAttrs,
|
|
2403
|
-
scriptNonce
|
|
2785
|
+
scriptNonce,
|
|
2786
|
+
{
|
|
2787
|
+
consentSnapshot: { consented, preferences },
|
|
2788
|
+
skipConsentCheck: true
|
|
2789
|
+
}
|
|
2404
2790
|
);
|
|
2405
2791
|
if (integration.init) {
|
|
2406
2792
|
integration.init();
|
|
@@ -2411,11 +2797,62 @@ function useConsentScriptLoader() {
|
|
|
2411
2797
|
return false;
|
|
2412
2798
|
}
|
|
2413
2799
|
},
|
|
2414
|
-
[preferences, consented]
|
|
2800
|
+
[preferences, consented, isHydrated]
|
|
2415
2801
|
);
|
|
2416
2802
|
}
|
|
2417
2803
|
|
|
2418
2804
|
// src/utils/scriptIntegrations.ts
|
|
2805
|
+
function buildConsentModeSignals(preferences) {
|
|
2806
|
+
const analytics = preferences.analytics ? "granted" : "denied";
|
|
2807
|
+
const marketing = preferences.marketing ? "granted" : "denied";
|
|
2808
|
+
return {
|
|
2809
|
+
ad_storage: marketing,
|
|
2810
|
+
ad_user_data: marketing,
|
|
2811
|
+
ad_personalization: marketing,
|
|
2812
|
+
analytics_storage: analytics
|
|
2813
|
+
};
|
|
2814
|
+
}
|
|
2815
|
+
function pushToLayer(entry, dataLayerName) {
|
|
2816
|
+
if (typeof globalThis.window === "undefined") return;
|
|
2817
|
+
const registry = globalThis.window;
|
|
2818
|
+
const name = dataLayerName ?? "dataLayer";
|
|
2819
|
+
const layer = registry[name] ?? [];
|
|
2820
|
+
registry[name] = layer;
|
|
2821
|
+
layer.push(entry);
|
|
2822
|
+
}
|
|
2823
|
+
function ensureGtag(dataLayerName = "dataLayer") {
|
|
2824
|
+
if (typeof globalThis.window === "undefined") return null;
|
|
2825
|
+
const w = window;
|
|
2826
|
+
const registry = w;
|
|
2827
|
+
const layer = registry[dataLayerName] ?? [];
|
|
2828
|
+
registry[dataLayerName] = layer;
|
|
2829
|
+
if (typeof w.gtag !== "function") {
|
|
2830
|
+
const gtag = (...args) => {
|
|
2831
|
+
layer.push(args);
|
|
2832
|
+
};
|
|
2833
|
+
w.gtag = gtag;
|
|
2834
|
+
}
|
|
2835
|
+
return w.gtag;
|
|
2836
|
+
}
|
|
2837
|
+
function applyDefaultConsentMode(dataLayerName) {
|
|
2838
|
+
const payload = buildConsentModeSignals({
|
|
2839
|
+
analytics: false,
|
|
2840
|
+
marketing: false
|
|
2841
|
+
});
|
|
2842
|
+
const gtag = ensureGtag(dataLayerName);
|
|
2843
|
+
if (gtag) {
|
|
2844
|
+
gtag("consent", "default", payload);
|
|
2845
|
+
}
|
|
2846
|
+
pushToLayer(["consent", "default", payload], dataLayerName);
|
|
2847
|
+
}
|
|
2848
|
+
function applyConsentModeUpdate(preferences, dataLayerName) {
|
|
2849
|
+
const payload = buildConsentModeSignals(preferences);
|
|
2850
|
+
const gtag = ensureGtag(dataLayerName);
|
|
2851
|
+
if (gtag) {
|
|
2852
|
+
gtag("consent", "update", payload);
|
|
2853
|
+
}
|
|
2854
|
+
pushToLayer(["consent", "update", payload], dataLayerName);
|
|
2855
|
+
}
|
|
2419
2856
|
function createGoogleAnalyticsIntegration(config) {
|
|
2420
2857
|
const src = config.scriptUrl ?? `https://www.googletagmanager.com/gtag/js?id=${config.measurementId}`;
|
|
2421
2858
|
return {
|
|
@@ -2443,17 +2880,17 @@ function createGoogleAnalyticsIntegration(config) {
|
|
|
2443
2880
|
provider: "Google Analytics"
|
|
2444
2881
|
}
|
|
2445
2882
|
],
|
|
2883
|
+
bootstrap: () => {
|
|
2884
|
+
applyDefaultConsentMode();
|
|
2885
|
+
},
|
|
2886
|
+
onConsentUpdate: ({ preferences }) => {
|
|
2887
|
+
applyConsentModeUpdate(preferences);
|
|
2888
|
+
},
|
|
2446
2889
|
init: () => {
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
w.dataLayer.push(...args);
|
|
2452
|
-
};
|
|
2453
|
-
w.gtag = gtag;
|
|
2454
|
-
gtag("js", /* @__PURE__ */ new Date());
|
|
2455
|
-
gtag("config", config.measurementId, config.config ?? {});
|
|
2456
|
-
}
|
|
2890
|
+
const gtag = ensureGtag();
|
|
2891
|
+
if (!gtag) return;
|
|
2892
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
2893
|
+
gtag("config", config.measurementId, config.config ?? {});
|
|
2457
2894
|
},
|
|
2458
2895
|
attrs: { async: "true" }
|
|
2459
2896
|
};
|
|
@@ -2465,6 +2902,12 @@ function createGoogleTagManagerIntegration(config) {
|
|
|
2465
2902
|
category: "analytics",
|
|
2466
2903
|
src,
|
|
2467
2904
|
cookies: ["_gcl_au"],
|
|
2905
|
+
bootstrap: () => {
|
|
2906
|
+
applyDefaultConsentMode(config.dataLayerName);
|
|
2907
|
+
},
|
|
2908
|
+
onConsentUpdate: ({ preferences }) => {
|
|
2909
|
+
applyConsentModeUpdate(preferences, config.dataLayerName);
|
|
2910
|
+
},
|
|
2468
2911
|
init: () => {
|
|
2469
2912
|
if (globalThis.window !== void 0) {
|
|
2470
2913
|
const dataLayerName = config.dataLayerName || "dataLayer";
|
|
@@ -3013,4 +3456,4 @@ var TEXT_TEMPLATES = {
|
|
|
3013
3456
|
}
|
|
3014
3457
|
};
|
|
3015
3458
|
|
|
3016
|
-
export { ANPD_CATEGORY_PRESETS, COMMON_INTEGRATIONS, ConsentGate, ConsentProvider, ConsentScriptLoader, DEFAULT_PROJECT_CATEGORIES, DesignProvider, EXPANDED_DEFAULT_TEXTS, GUIDANCE_PRESETS, INTEGRATION_TEMPLATES, LogLevel, TEXT_TEMPLATES, analyzeDeveloperConfiguration, analyzeIntegrationCategories, autoConfigureCategories, buildConsentStorageKey, categorizeDiscoveredCookies, checkPeerDeps, createAnpdCategoriesConfig, createClarityIntegration, createConsentAuditEntry, createCorporateIntegrations, createECommerceIntegrations, createFacebookPixelIntegration, createGoogleAnalyticsIntegration, createGoogleTagManagerIntegration, createHotjarIntegration, createIntercomIntegration, createMixpanelIntegration, createProjectPreferences, createSaaSIntegrations, createUserWayIntegration, createZendeskChatIntegration, defaultTexts, detectConsentCookieName, discoverRuntimeCookies, ensureNecessaryAlwaysOn, extractCategoriesFromIntegrations, getAllProjectCategories, getCookiesInfoForCategory, loadScript, logDeveloperGuidance, logger, openPreferencesModal, pushConsentInitializedEvent, pushConsentUpdatedEvent, resolveTexts, runPeerDepsCheck, setCookieCatalogOverrides, setCookieCategoryOverrides, setDebugLogging, suggestCategoryForScript, useCategories, useCategoryStatus, useConsent, useConsentHydration, useConsentScriptLoader, useConsentTexts, useDataLayerEvents, useDesignTokens, useDeveloperGuidance, useOpenPreferencesModal, validateIntegrationCategories, validateNecessaryClassification, validateProjectPreferences };
|
|
3459
|
+
export { ANPD_CATEGORY_PRESETS, COMMON_INTEGRATIONS, ConsentGate, ConsentProvider, ConsentScriptLoader, DEFAULT_PROJECT_CATEGORIES, DesignProvider, EXPANDED_DEFAULT_TEXTS, GUIDANCE_PRESETS, INTEGRATION_TEMPLATES, LogLevel, TEXT_TEMPLATES, analyzeDeveloperConfiguration, analyzeIntegrationCategories, autoConfigureCategories, buildConsentStorageKey, categorizeDiscoveredCookies, checkPeerDeps, createAnpdCategoriesConfig, createClarityIntegration, createConsentAuditEntry, createCorporateIntegrations, createECommerceIntegrations, createFacebookPixelIntegration, createGoogleAnalyticsIntegration, createGoogleTagManagerIntegration, createHotjarIntegration, createIntercomIntegration, createMixpanelIntegration, createProjectPreferences, createSaaSIntegrations, createUserWayIntegration, createZendeskChatIntegration, defaultTexts, detectConsentCookieName, discoverRuntimeCookies, ensureNecessaryAlwaysOn, extractCategoriesFromIntegrations, getAllProjectCategories, getCookiesInfoForCategory, getPeerDepsLocale, loadScript, logDeveloperGuidance, logger, openPreferencesModal, pushConsentInitializedEvent, pushConsentUpdatedEvent, registerScript, resetPeerDepsMessages, resolveTexts, runPeerDepsCheck, setCookieCatalogOverrides, setCookieCategoryOverrides, setDebugLogging, setPeerDepsLocale, setPeerDepsMessages, suggestCategoryForScript, useCategories, useCategoryStatus, useConsent, useConsentHydration, useConsentScriptLoader, useConsentTexts, useDataLayerEvents, useDesignTokens, useDeveloperGuidance, useOpenPreferencesModal, validateIntegrationCategories, validateNecessaryClassification, validateProjectPreferences };
|