@react-lgpd-consent/core 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11,6 +11,219 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
11
11
  throw Error('Dynamic require of "' + x + '" is not supported');
12
12
  });
13
13
 
14
+ // src/types/advancedTexts.ts
15
+ var EXPANDED_DEFAULT_TEXTS = {
16
+ // Textos adicionais
17
+ confirm: "Confirmar",
18
+ cancel: "Cancelar",
19
+ loading: "Carregando...",
20
+ // Feedback
21
+ feedback: {
22
+ saveSuccess: "Prefer\xEAncias salvas com sucesso!",
23
+ saveError: "Erro ao salvar prefer\xEAncias. Tente novamente.",
24
+ consentUpdated: "Consentimento atualizado.",
25
+ cookiesRejected: "Cookies opcionais rejeitados.",
26
+ settingsReset: "Configura\xE7\xF5es resetadas."
27
+ },
28
+ // Acessibilidade
29
+ accessibility: {
30
+ bannerLabel: "Banner de consentimento de cookies",
31
+ modalLabel: "Modal de prefer\xEAncias de cookies",
32
+ keyboardNavigation: "Use Tab para navegar, Enter para selecionar",
33
+ toggleState: {
34
+ enabled: "Habilitado",
35
+ disabled: "Desabilitado"
36
+ },
37
+ liveRegion: "Regi\xE3o de an\xFAncios din\xE2micos"
38
+ },
39
+ // Categorias
40
+ categories: {
41
+ necessary: {
42
+ name: "Cookies Necess\xE1rios",
43
+ description: "Essenciais para o funcionamento b\xE1sico do site",
44
+ examples: "Sess\xE3o, seguran\xE7a, prefer\xEAncias de idioma"
45
+ },
46
+ analytics: {
47
+ name: "Cookies de Analytics",
48
+ description: "Ajudam a entender como os visitantes usam o site",
49
+ examples: "Google Analytics, contadores de p\xE1gina"
50
+ },
51
+ marketing: {
52
+ name: "Cookies de Marketing",
53
+ description: "Usados para personalizar an\xFAncios e ofertas",
54
+ examples: "Facebook Pixel, Google Ads, remarketing"
55
+ },
56
+ functional: {
57
+ name: "Cookies Funcionais",
58
+ description: "Melhoram a funcionalidade e personaliza\xE7\xE3o",
59
+ examples: "Chat, mapas, v\xEDdeos embarcados"
60
+ },
61
+ performance: {
62
+ name: "Cookies de Performance",
63
+ description: "Coletam informa\xE7\xF5es sobre velocidade e estabilidade",
64
+ examples: "Monitoramento de erro, otimiza\xE7\xE3o de velocidade"
65
+ }
66
+ },
67
+ // Contextos específicos
68
+ contexts: {
69
+ ecommerce: {
70
+ cartAbandonment: "Lembramos dos produtos no seu carrinho",
71
+ personalizedOffers: "Ofertas personalizadas baseadas no seu hist\xF3rico",
72
+ paymentSecurity: "Seguran\xE7a adicional no processo de pagamento",
73
+ productRecommendations: "Sugest\xF5es de produtos relevantes"
74
+ },
75
+ saas: {
76
+ userAnalytics: "An\xE1lise de uso para melhorar funcionalidades",
77
+ performanceMonitoring: "Monitoramento de performance da aplica\xE7\xE3o",
78
+ featureUsage: "Estat\xEDsticas de uso de recursos",
79
+ customerSupport: "Suporte ao cliente mais eficiente"
80
+ },
81
+ government: {
82
+ citizenServices: "Melhoria dos servi\xE7os ao cidad\xE3o",
83
+ dataProtection: "Prote\xE7\xE3o rigorosa dos dados pessoais",
84
+ transparency: "Transpar\xEAncia no uso de dados",
85
+ accessibility: "Recursos de acessibilidade digital"
86
+ },
87
+ education: {
88
+ studentProgress: "Acompanhamento do progresso educacional",
89
+ learningAnalytics: "Analytics para melhorar o aprendizado",
90
+ accessibility: "Recursos educacionais acess\xEDveis",
91
+ parentalConsent: "Consentimento parental quando necess\xE1rio"
92
+ }
93
+ },
94
+ // Variações de tom
95
+ variants: {
96
+ formal: {
97
+ bannerMessage: "Este s\xEDtio eletr\xF4nico utiliza cookies para otimizar a experi\xEAncia de navega\xE7\xE3o.",
98
+ acceptAll: "Concordar com todos os cookies",
99
+ declineAll: "Recusar cookies opcionais",
100
+ modalTitle: "Configura\xE7\xE3o de Cookies"
101
+ },
102
+ casual: {
103
+ bannerMessage: "\u{1F36A} Ei! Usamos cookies para tornar sua experi\xEAncia ainda melhor!",
104
+ acceptAll: "Aceitar tudo",
105
+ declineAll: "S\xF3 o essencial",
106
+ modalTitle: "Seus Cookies"
107
+ },
108
+ concise: {
109
+ bannerMessage: "Usamos cookies. Voc\xEA aceita?",
110
+ acceptAll: "Sim",
111
+ declineAll: "N\xE3o",
112
+ modalTitle: "Cookies"
113
+ },
114
+ detailed: {
115
+ bannerMessage: "Utilizamos cookies e tecnologias similares para melhorar sua experi\xEAncia de navega\xE7\xE3o, personalizar conte\xFAdo, analisar tr\xE1fego e oferecer funcionalidades de redes sociais.",
116
+ acceptAll: "Aceitar todos os cookies e tecnologias",
117
+ declineAll: "Recusar todos os cookies opcionais",
118
+ modalTitle: "Centro de Prefer\xEAncias de Privacidade"
119
+ }
120
+ },
121
+ // Internacionalização simplificada (apenas textos básicos)
122
+ i18n: {
123
+ en: {
124
+ bannerMessage: "We use cookies to enhance your experience.",
125
+ acceptAll: "Accept All",
126
+ declineAll: "Decline",
127
+ preferences: "Preferences",
128
+ modalTitle: "Cookie Preferences",
129
+ modalIntro: "Customize your cookie preferences below.",
130
+ save: "Save Preferences",
131
+ necessaryAlwaysOn: "Necessary cookies (always active)"
132
+ },
133
+ es: {
134
+ bannerMessage: "Utilizamos cookies para mejorar su experiencia.",
135
+ acceptAll: "Aceptar Todo",
136
+ declineAll: "Rechazar",
137
+ preferences: "Preferencias",
138
+ modalTitle: "Preferencias de Cookies",
139
+ modalIntro: "Personalice sus preferencias de cookies a continuaci\xF3n.",
140
+ save: "Guardar Preferencias",
141
+ necessaryAlwaysOn: "Cookies necess\xE1rias (sempre ativas)"
142
+ },
143
+ fr: {
144
+ bannerMessage: "Nous utilisons des cookies pour am\xE9liorer votre exp\xE9rience.",
145
+ acceptAll: "Tout Accepter",
146
+ declineAll: "Refuser",
147
+ preferences: "Pr\xE9f\xE9rences",
148
+ modalTitle: "Pr\xE9f\xE9rences des Cookies",
149
+ modalIntro: "Personnalisez vos pr\xE9f\xE9rences de cookies ci-dessous.",
150
+ save: "Enregistrer les Pr\xE9f\xE9rences",
151
+ necessaryAlwaysOn: "Cookies n\xE9cessaires (toujours actifs)"
152
+ }
153
+ },
154
+ // Textos técnicos
155
+ technical: {
156
+ sessionCookies: "Cookies de sess\xE3o s\xE3o tempor\xE1rios e expiram quando voc\xEA fecha o navegador.",
157
+ persistentCookies: "Cookies persistentes permanecem no seu dispositivo at\xE9 expirarem ou serem removidos.",
158
+ thirdPartyCookies: "Cookies de terceiros s\xE3o definidos por dom\xEDnios diferentes do site que voc\xEA est\xE1 visitando.",
159
+ browserSettings: "Voc\xEA pode gerenciar cookies nas configura\xE7\xF5es do seu navegador.",
160
+ disablingImpact: "Desabilitar cookies pode afetar a funcionalidade do site."
161
+ },
162
+ // Cookie details
163
+ cookieDetails: {
164
+ tableHeaders: {
165
+ name: "Nome",
166
+ purpose: "Finalidade",
167
+ duration: "Dura\xE7\xE3o",
168
+ provider: "Fornecedor",
169
+ type: "Tipo"
170
+ },
171
+ noCookies: "Nenhum cookie encontrado para esta categoria.",
172
+ toggleDetails: {
173
+ expand: "Ver detalhes",
174
+ collapse: "Ocultar detalhes"
175
+ },
176
+ scriptLabelPrefix: "(script) ",
177
+ scriptPurpose: "Script de integra\xE7\xE3o ativo"
178
+ }
179
+ };
180
+ function resolveTexts(texts, options = {}) {
181
+ const { language = "pt", variant } = options;
182
+ let resolved = { ...texts };
183
+ if (variant && texts.variants?.[variant]) {
184
+ resolved = { ...resolved, ...texts.variants[variant] };
185
+ }
186
+ if (language !== "pt" && texts.i18n?.[language]) {
187
+ resolved = { ...resolved, ...texts.i18n[language] };
188
+ }
189
+ return resolved;
190
+ }
191
+ var TEXT_TEMPLATES = {
192
+ ecommerce: {
193
+ ...EXPANDED_DEFAULT_TEXTS,
194
+ bannerMessage: "Utilizamos cookies para personalizar ofertas e melhorar sua experi\xEAncia de compra.",
195
+ acceptAll: "Aceitar e continuar",
196
+ variants: {
197
+ casual: {
198
+ bannerMessage: "\u{1F6D2} Usamos cookies para encontrar as melhores ofertas para voc\xEA!",
199
+ acceptAll: "Quero ofertas personalizadas!"
200
+ }
201
+ }
202
+ },
203
+ saas: {
204
+ ...EXPANDED_DEFAULT_TEXTS,
205
+ bannerMessage: "Utilizamos cookies para otimizar o desempenho da aplica\xE7\xE3o e sua experi\xEAncia.",
206
+ acceptAll: "Aceitar e otimizar",
207
+ variants: {
208
+ formal: {
209
+ bannerMessage: "Esta aplica\xE7\xE3o utiliza cookies para an\xE1lise de performance e melhoria cont\xEDnua da experi\xEAncia do usu\xE1rio.",
210
+ acceptAll: "Autorizar coleta de dados de uso"
211
+ }
212
+ }
213
+ },
214
+ government: {
215
+ ...EXPANDED_DEFAULT_TEXTS,
216
+ bannerMessage: "Este portal utiliza cookies em conformidade com a LGPD para melhorar os servi\xE7os p\xFAblicos.",
217
+ acceptAll: "Aceitar em conformidade",
218
+ variants: {
219
+ formal: {
220
+ bannerMessage: "Este s\xEDtio eletr\xF4nico do governo utiliza cookies estritamente necess\xE1rios e opcionais, em conformidade com a Lei Geral de Prote\xE7\xE3o de Dados.",
221
+ acceptAll: "Concordar com o uso de cookies"
222
+ }
223
+ }
224
+ }
225
+ };
226
+
14
227
  // src/utils/categoryUtils.ts
15
228
  function createProjectPreferences(config, defaultValue = false) {
16
229
  const preferences = {
@@ -309,6 +522,7 @@ function setDebugLogging(enabled, level = 2 /* INFO */) {
309
522
  // src/utils/cookieUtils.ts
310
523
  var DEFAULT_STORAGE_NAMESPACE = "lgpd-consent";
311
524
  var DEFAULT_STORAGE_VERSION = "1";
525
+ var DEFAULT_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;
312
526
  function buildConsentStorageKey(options) {
313
527
  const namespaceRaw = options?.namespace?.trim() || DEFAULT_STORAGE_NAMESPACE;
314
528
  const versionRaw = options?.version?.trim() || DEFAULT_STORAGE_VERSION;
@@ -318,16 +532,36 @@ function buildConsentStorageKey(options) {
318
532
  }
319
533
  var DEFAULT_COOKIE_OPTS = {
320
534
  name: "cookieConsent",
535
+ maxAge: DEFAULT_MAX_AGE_SECONDS,
321
536
  maxAgeDays: 365,
322
537
  sameSite: "Lax",
323
- secure: globalThis.window === void 0 ? false : globalThis.window.location.protocol === "https:",
538
+ secure: false,
324
539
  path: "/",
325
540
  domain: void 0
326
541
  };
542
+ function resolveCookieOptions(opts) {
543
+ const currentWindow = globalThis.window;
544
+ const currentLocation = globalThis.location;
545
+ const protocols = [currentWindow?.location?.protocol, currentLocation?.protocol].filter(
546
+ Boolean
547
+ );
548
+ const forceHttps = globalThis.__LGPD_FORCE_HTTPS__ === true;
549
+ const isHttps = forceHttps || protocols.includes("https:");
550
+ const maxAgeSecondsFromDays = typeof opts?.maxAgeDays === "number" ? Math.max(0, opts.maxAgeDays * 24 * 60 * 60) : null;
551
+ const maxAgeSeconds = typeof opts?.maxAge === "number" ? Math.max(0, opts.maxAge) : maxAgeSecondsFromDays ?? DEFAULT_MAX_AGE_SECONDS;
552
+ return {
553
+ name: opts?.name ?? DEFAULT_COOKIE_OPTS.name,
554
+ maxAge: maxAgeSeconds,
555
+ sameSite: opts?.sameSite ?? DEFAULT_COOKIE_OPTS.sameSite ?? "Lax",
556
+ secure: typeof opts?.secure === "boolean" ? opts.secure : isHttps ? true : DEFAULT_COOKIE_OPTS.secure,
557
+ path: opts?.path ?? DEFAULT_COOKIE_OPTS.path ?? "/",
558
+ domain: opts?.domain ?? DEFAULT_COOKIE_OPTS.domain ?? void 0
559
+ };
560
+ }
327
561
  var COOKIE_SCHEMA_VERSION = "1.0";
328
562
  function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
329
563
  logger.debug("Reading consent cookie", { name });
330
- if (typeof document === "undefined") {
564
+ if (globalThis.document === void 0) {
331
565
  logger.debug("Cookie read skipped: server-side environment");
332
566
  return null;
333
567
  }
@@ -339,6 +573,10 @@ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
339
573
  try {
340
574
  const data = JSON.parse(raw);
341
575
  logger.cookieOperation("read", name, data);
576
+ if (!data || typeof data !== "object") {
577
+ logger.warn("Consent cookie malformed: payload is not an object");
578
+ return null;
579
+ }
342
580
  if (!data.version) {
343
581
  logger.debug("Migrating legacy cookie format");
344
582
  return migrateLegacyCookie(data);
@@ -347,7 +585,11 @@ function readConsentCookie(name = DEFAULT_COOKIE_OPTS.name) {
347
585
  logger.warn(`Cookie version mismatch: ${data.version} != ${COOKIE_SCHEMA_VERSION}`);
348
586
  return null;
349
587
  }
350
- return data;
588
+ const preferences = data && typeof data.preferences === "object" ? data.preferences : { necessary: true };
589
+ return {
590
+ ...data,
591
+ preferences: ensureNecessaryAlwaysOn(preferences)
592
+ };
351
593
  } catch (error) {
352
594
  logger.error("Error parsing consent cookie", error);
353
595
  return null;
@@ -370,12 +612,12 @@ function migrateLegacyCookie(legacyData) {
370
612
  }
371
613
  }
372
614
  function writeConsentCookie(state, config, opts, source = "banner") {
373
- if (typeof document === "undefined") {
615
+ if (globalThis.document === void 0 || globalThis.window === void 0 || globalThis.__LGPD_SSR__ === true) {
374
616
  logger.debug("Cookie write skipped: server-side environment");
375
617
  return;
376
618
  }
377
619
  const now = (/* @__PURE__ */ new Date()).toISOString();
378
- const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
620
+ const o = resolveCookieOptions(opts);
379
621
  const preferences = ensureNecessaryAlwaysOn(state.preferences);
380
622
  const cookieData = {
381
623
  version: COOKIE_SCHEMA_VERSION,
@@ -387,8 +629,9 @@ function writeConsentCookie(state, config, opts, source = "banner") {
387
629
  projectConfig: config
388
630
  };
389
631
  logger.cookieOperation("write", o.name, cookieData);
632
+ const expires = new Date(Date.now() + o.maxAge * 1e3);
390
633
  Cookies.set(o.name, JSON.stringify(cookieData), {
391
- expires: o.maxAgeDays,
634
+ expires,
392
635
  sameSite: o.sameSite,
393
636
  secure: o.secure,
394
637
  path: o.path,
@@ -418,36 +661,48 @@ function createConsentAuditEntry(state, params) {
418
661
  };
419
662
  }
420
663
  function removeConsentCookie(opts) {
421
- if (typeof document === "undefined") {
664
+ if (globalThis.document === void 0) {
422
665
  logger.debug("Cookie removal skipped: server-side environment");
423
666
  return;
424
667
  }
425
- const o = { ...DEFAULT_COOKIE_OPTS, ...opts };
668
+ const o = resolveCookieOptions(opts);
426
669
  logger.cookieOperation("delete", o.name);
427
670
  Cookies.remove(o.name, { path: o.path, domain: o.domain });
428
671
  logger.info("Consent cookie removed");
429
672
  }
430
673
 
431
674
  // src/utils/dataLayerEvents.ts
432
- var LIBRARY_VERSION = "0.7.0";
675
+ var LIBRARY_VERSION = "0.7.2";
433
676
  function ensureDataLayer() {
434
- var _a;
435
- if (globalThis.window === void 0) return;
436
- (_a = globalThis.window).dataLayer ?? (_a.dataLayer = []);
677
+ const currentWindow = globalThis.window;
678
+ if (!currentWindow) return;
679
+ const currentLayer = currentWindow.dataLayer;
680
+ if (currentLayer == null) {
681
+ currentWindow.dataLayer = [];
682
+ return;
683
+ }
684
+ if (typeof currentLayer.push !== "function") {
685
+ const env = globalThis.process?.env?.NODE_ENV ?? "production";
686
+ if (env !== "production") {
687
+ console.warn("[LGPD-CONSENT] dataLayer presente mas sem push; eventos n\xE3o ser\xE3o registrados.");
688
+ }
689
+ }
437
690
  }
438
691
  function pushConsentInitializedEvent(categories) {
439
- if (globalThis.window === void 0) return;
440
692
  ensureDataLayer();
441
693
  const event = {
442
694
  event: "consent_initialized",
443
695
  consent_version: LIBRARY_VERSION,
444
696
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
445
- categories
697
+ categories,
698
+ preferences: categories
446
699
  };
447
- globalThis.window.dataLayer?.push(event);
700
+ const layer = globalThis.window?.dataLayer;
701
+ if (layer && typeof layer.push === "function") {
702
+ layer.push(event);
703
+ }
448
704
  }
449
705
  function pushConsentUpdatedEvent(categories, origin, previousCategories) {
450
- if (globalThis.window === void 0) return;
451
706
  ensureDataLayer();
452
707
  const changedCategories = previousCategories ? Object.keys(categories).filter((key) => categories[key] !== previousCategories[key]) : [];
453
708
  const event = {
@@ -456,9 +711,13 @@ function pushConsentUpdatedEvent(categories, origin, previousCategories) {
456
711
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
457
712
  origin,
458
713
  categories,
714
+ preferences: categories,
459
715
  changed_categories: changedCategories
460
716
  };
461
- globalThis.window.dataLayer?.push(event);
717
+ const layer = globalThis.window?.dataLayer;
718
+ if (layer && typeof layer.push === "function") {
719
+ layer.push(event);
720
+ }
462
721
  }
463
722
  function useDataLayerEvents() {
464
723
  return {
@@ -788,7 +1047,7 @@ function analyzeDeveloperConfiguration(config) {
788
1047
  const gt = globalThis;
789
1048
  const implied = (gt.__LGPD_REQUIRED_CATEGORIES__ || []).filter(Boolean);
790
1049
  implied.forEach((id) => {
791
- if (!guidance.activeCategoriesInfo.find((c) => c.id === id)) {
1050
+ if (!guidance.activeCategoriesInfo.some((c) => c.id === id)) {
792
1051
  const info = NAMES[id];
793
1052
  if (info) {
794
1053
  guidance.activeCategoriesInfo.push({
@@ -828,6 +1087,27 @@ function analyzeDeveloperConfiguration(config) {
828
1087
  'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.',
829
1088
  "compliance"
830
1089
  );
1090
+ } else {
1091
+ addMessage(
1092
+ "info",
1093
+ "Cookies n\xE3o necess\xE1rios devem iniciar desativados e exigir consentimento expresso, sem pr\xE9-sele\xE7\xE3o e sem consentimento t\xE1cito.",
1094
+ "consent"
1095
+ );
1096
+ addMessage(
1097
+ "info",
1098
+ "Ofere\xE7a op\xE7\xF5es claras de aceitar, rejeitar e gerenciar prefer\xEAncias com o mesmo destaque, al\xE9m de revoga\xE7\xE3o simples e gratuita.",
1099
+ "consent"
1100
+ );
1101
+ addMessage(
1102
+ "info",
1103
+ "Informe finalidades espec\xEDficas, per\xEDodo de reten\xE7\xE3o e compartilhamento com terceiros em pol\xEDtica/aviso de cookies.",
1104
+ "transparency"
1105
+ );
1106
+ addMessage(
1107
+ "info",
1108
+ "Disponibilize mecanismo pr\xF3prio de gerenciamento de cookies; configura\xE7\xF5es do navegador s\xE3o apenas complementares.",
1109
+ "transparency"
1110
+ );
831
1111
  }
832
1112
  if (totalToggleable > 5) {
833
1113
  addMessage(
@@ -852,7 +1132,7 @@ function getComplianceScoreColor(score) {
852
1132
  function logComplianceScore(prefix, score) {
853
1133
  const color = getComplianceScoreColor(score);
854
1134
  console.log(
855
- `%c${prefix} Score de Conformidade LGPD: ${score}/100`,
1135
+ `%c${prefix} Score de Conformidade LGPD (orientativo): ${score}/100`,
856
1136
  `color: ${color}; font-weight: bold; font-size: 14px;`
857
1137
  );
858
1138
  }
@@ -947,7 +1227,7 @@ function logServerSideIfAvailable(guidance) {
947
1227
  }
948
1228
  function logDeveloperGuidance(guidance, disableGuidanceProp, config) {
949
1229
  const gt = globalThis;
950
- const nodeEnv = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
1230
+ const nodeEnv = gt.process ? gt.process?.env?.NODE_ENV : void 0;
951
1231
  const isProd = nodeEnv === "production" || gt.__LGPD_PRODUCTION__ === true;
952
1232
  if (isProd || disableGuidanceProp) return;
953
1233
  const guidanceHash = getGuidanceHash(guidance);
@@ -1005,11 +1285,21 @@ function logDeveloperGuidance(guidance, disableGuidanceProp, config) {
1005
1285
  "color: #9c27b0;",
1006
1286
  "color: #7b1fa2;"
1007
1287
  );
1288
+ console.info(
1289
+ `%c${PREFIX}%c Evite consentimento t\xE1cito e op\xE7\xF5es pr\xE9-selecionadas`,
1290
+ "color: #9c27b0;",
1291
+ "color: #7b1fa2;"
1292
+ );
1008
1293
  console.info(
1009
1294
  `%c${PREFIX}%c Documente pol\xEDticas claras por categoria`,
1010
1295
  "color: #9c27b0;",
1011
1296
  "color: #7b1fa2;"
1012
1297
  );
1298
+ console.info(
1299
+ `%c${PREFIX}%c Informe finalidades, reten\xE7\xE3o e revoga\xE7\xE3o simples e gratuita`,
1300
+ "color: #9c27b0;",
1301
+ "color: #7b1fa2;"
1302
+ );
1013
1303
  console.info(
1014
1304
  `%c${PREFIX}%c Registre consentimento com data/hora/origem`,
1015
1305
  "color: #9c27b0;",
@@ -1021,7 +1311,9 @@ function logDeveloperGuidance(guidance, disableGuidanceProp, config) {
1021
1311
  function useDeveloperGuidance(config, disableGuidanceProp, guidanceConfig) {
1022
1312
  const guidance = React4__default.useMemo(() => analyzeDeveloperConfiguration(config), [config]);
1023
1313
  React4__default.useEffect(() => {
1024
- if (!disableGuidanceProp) logDeveloperGuidance(guidance, disableGuidanceProp, guidanceConfig);
1314
+ if (globalThis.window !== void 0 && !disableGuidanceProp) {
1315
+ logDeveloperGuidance(guidance, disableGuidanceProp, guidanceConfig);
1316
+ }
1025
1317
  }, [guidance, disableGuidanceProp, guidanceConfig]);
1026
1318
  return guidance;
1027
1319
  }
@@ -1065,58 +1357,8 @@ var GUIDANCE_PRESETS = {
1065
1357
  };
1066
1358
 
1067
1359
  // src/utils/peerDepsCheck.ts
1068
- function detectMultipleReactInstances() {
1069
- if (globalThis.window === void 0) return false;
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 = `
1360
+ var MESSAGES_PT_BR = {
1361
+ MULTIPLE_REACT_INSTANCES: `
1120
1362
  \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
1363
  \u2551 \u26A0\uFE0F ERRO: M\xFAltiplas inst\xE2ncias de React detectadas \u2551
1122
1364
  \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 +1420,13 @@ function checkPeerDeps(options = {}) {
1178
1420
  https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#multiple-react-instances
1179
1421
 
1180
1422
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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
- result.errors.push(errorMsg);
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 = `
1423
+ `,
1424
+ UNSUPPORTED_REACT_VERSION: (version) => `
1192
1425
  \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
1426
  \u2551 \u26A0\uFE0F AVISO: Vers\xE3o do React n\xE3o suportada \u2551
1194
1427
  \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
1428
 
1196
- \u{1F4E6} Vers\xE3o detectada: React ${reactVersion}
1429
+ \u{1F4E6} Vers\xE3o detectada: React ${version}
1197
1430
  \u2705 Vers\xF5es suportadas: React 18.x ou 19.x
1198
1431
 
1199
1432
  \u{1F50D} O react-lgpd-consent requer React 18.2.0+ ou React 19.x
@@ -1211,27 +1444,13 @@ function checkPeerDeps(options = {}) {
1211
1444
  https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#react-version
1212
1445
 
1213
1446
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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
- result.errors.push(errorMsg);
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
- `
1447
+ `,
1448
+ UNSUPPORTED_MUI_VERSION: (version) => `
1230
1449
  \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
1450
  \u2551 \u26A0\uFE0F AVISO: Vers\xE3o do Material-UI fora do range recomendado \u2551
1232
1451
  \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
1452
 
1234
- \u{1F4E6} Vers\xE3o detectada: @mui/material ${muiVersion}
1453
+ \u{1F4E6} Vers\xE3o detectada: @mui/material ${version}
1235
1454
  \u2705 Vers\xF5es suportadas: 5.15.0+, 6.x, 7.x
1236
1455
 
1237
1456
  \u{1F50D} Componentes de UI (@react-lgpd-consent/mui) podem apresentar problemas.
@@ -1249,8 +1468,230 @@ function checkPeerDeps(options = {}) {
1249
1468
  https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#mui-version
1250
1469
 
1251
1470
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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
- );
1471
+ `,
1472
+ 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.`
1473
+ };
1474
+ var MESSAGES_EN = {
1475
+ MULTIPLE_REACT_INSTANCES: `
1476
+ \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
1477
+ \u2551 \u26A0\uFE0F ERROR: Multiple React instances detected \u2551
1478
+ \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
1479
+
1480
+ \u{1F534} Problem:
1481
+ Your project is loading more than one copy of React, causing the error:
1482
+ "Invalid hook call. Hooks can only be called inside of the body of a
1483
+ function component."
1484
+
1485
+ \u{1F50D} Probable cause:
1486
+ \u2022 pnpm/Yarn PnP without proper peer dependency hoisting
1487
+ \u2022 node_modules with duplicate React (classic npm/yarn)
1488
+ \u2022 Webpack/Vite with multiple resolutions of the same package
1489
+
1490
+ \u2705 Solutions:
1491
+
1492
+ \u{1F4E6} PNPM (RECOMMENDED):
1493
+ Add to root package.json:
1494
+ {
1495
+ "pnpm": {
1496
+ "overrides": {
1497
+ "react": "$react",
1498
+ "react-dom": "$react-dom"
1499
+ }
1500
+ }
1501
+ }
1502
+ Run: pnpm install
1503
+
1504
+ \u{1F4E6} NPM/Yarn:
1505
+ Add to root package.json:
1506
+ {
1507
+ "overrides": {
1508
+ "react": "^18.2.0 || ^19.0.0",
1509
+ "react-dom": "^18.2.0 || ^19.0.0"
1510
+ }
1511
+ }
1512
+ Run: npm install (or yarn install)
1513
+
1514
+ \u{1F527} Webpack:
1515
+ Add to webpack.config.js:
1516
+ module.exports = {
1517
+ resolve: {
1518
+ alias: {
1519
+ react: path.resolve('./node_modules/react'),
1520
+ 'react-dom': path.resolve('./node_modules/react-dom'),
1521
+ }
1522
+ }
1523
+ }
1524
+
1525
+ \u26A1 Vite:
1526
+ Add to vite.config.js:
1527
+ export default {
1528
+ resolve: {
1529
+ dedupe: ['react', 'react-dom']
1530
+ }
1531
+ }
1532
+
1533
+ \u{1F4DA} Documentation:
1534
+ https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#multiple-react-instances
1535
+
1536
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1537
+ `,
1538
+ UNSUPPORTED_REACT_VERSION: (version) => `
1539
+ \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
1540
+ \u2551 \u26A0\uFE0F WARNING: Unsupported React version \u2551
1541
+ \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
1542
+
1543
+ \u{1F4E6} Detected version: React ${version}
1544
+ \u2705 Supported versions: React 18.x or 19.x
1545
+
1546
+ \u{1F50D} react-lgpd-consent requires React 18.2.0+ or React 19.x
1547
+
1548
+ \u2705 Solution:
1549
+ Update React to a supported version:
1550
+
1551
+ npm install react@^18.2.0 react-dom@^18.2.0
1552
+
1553
+ or
1554
+
1555
+ npm install react@^19.0.0 react-dom@^19.0.0
1556
+
1557
+ \u{1F4DA} Documentation:
1558
+ https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#react-version
1559
+
1560
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1561
+ `,
1562
+ UNSUPPORTED_MUI_VERSION: (version) => `
1563
+ \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
1564
+ \u2551 \u26A0\uFE0F WARNING: Material-UI version out of recommended range \u2551
1565
+ \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
1566
+
1567
+ \u{1F4E6} Detected version: @mui/material ${version}
1568
+ \u2705 Supported versions: 5.15.0+, 6.x, 7.x
1569
+
1570
+ \u{1F50D} UI components (@react-lgpd-consent/mui) may have issues.
1571
+
1572
+ \u2705 Solution:
1573
+ Update MUI to a supported version:
1574
+
1575
+ npm install @mui/material@^7.0.0 @emotion/react @emotion/styled
1576
+
1577
+ or keep 5.15.0+:
1578
+
1579
+ npm install @mui/material@^5.15.0 @emotion/react @emotion/styled
1580
+
1581
+ \u{1F4DA} Documentation:
1582
+ https://github.com/lucianoedipo/react-lgpd-consent/blob/main/TROUBLESHOOTING.md#mui-version
1583
+
1584
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
1585
+ `,
1586
+ 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.`
1587
+ };
1588
+ var MESSAGES_BY_LOCALE = {
1589
+ "pt-BR": MESSAGES_PT_BR,
1590
+ en: MESSAGES_EN
1591
+ };
1592
+ var currentLocale = "pt-BR";
1593
+ var customMessages = {};
1594
+ function setPeerDepsLocale(locale) {
1595
+ currentLocale = locale;
1596
+ }
1597
+ function getPeerDepsLocale() {
1598
+ return currentLocale;
1599
+ }
1600
+ function setPeerDepsMessages(messages) {
1601
+ customMessages = { ...customMessages, ...messages };
1602
+ }
1603
+ function resetPeerDepsMessages() {
1604
+ customMessages = {};
1605
+ }
1606
+ function getMessages() {
1607
+ const baseMessages = MESSAGES_BY_LOCALE[currentLocale];
1608
+ if (Object.keys(customMessages).length === 0) {
1609
+ return baseMessages;
1610
+ }
1611
+ return {
1612
+ MULTIPLE_REACT_INSTANCES: customMessages.MULTIPLE_REACT_INSTANCES ?? baseMessages.MULTIPLE_REACT_INSTANCES,
1613
+ UNSUPPORTED_REACT_VERSION: customMessages.UNSUPPORTED_REACT_VERSION ?? baseMessages.UNSUPPORTED_REACT_VERSION,
1614
+ UNSUPPORTED_MUI_VERSION: customMessages.UNSUPPORTED_MUI_VERSION ?? baseMessages.UNSUPPORTED_MUI_VERSION,
1615
+ MUI_OUT_OF_RANGE: customMessages.MUI_OUT_OF_RANGE ?? baseMessages.MUI_OUT_OF_RANGE
1616
+ };
1617
+ }
1618
+ function detectMultipleReactInstances() {
1619
+ const currentWindow = globalThis.window;
1620
+ if (currentWindow === void 0) return false;
1621
+ try {
1622
+ const reactSymbols = Object.getOwnPropertySymbols(currentWindow).map(String).filter((name) => name.includes("react"));
1623
+ if (reactSymbols.length > 1) {
1624
+ return true;
1625
+ }
1626
+ const ReactModule = currentWindow.React;
1627
+ if (ReactModule && Array.isArray(ReactModule)) {
1628
+ return true;
1629
+ }
1630
+ const hasMultipleVersions = (currentWindow.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers?.size ?? 0) > 1;
1631
+ return hasMultipleVersions || false;
1632
+ } catch {
1633
+ return false;
1634
+ }
1635
+ }
1636
+ function getPackageVersion(packageName) {
1637
+ const currentWindow = globalThis.window;
1638
+ if (currentWindow === void 0) return null;
1639
+ try {
1640
+ const pkg = currentWindow[packageName];
1641
+ if (pkg?.version) return pkg.version;
1642
+ const React6 = currentWindow.React;
1643
+ if (packageName === "react" && React6?.version) {
1644
+ return React6.version;
1645
+ }
1646
+ return null;
1647
+ } catch {
1648
+ return null;
1649
+ }
1650
+ }
1651
+ function isVersionInRange(version, minMajor, maxMajor) {
1652
+ const major = Number.parseInt(version.split(".")[0], 10);
1653
+ return major >= minMajor && major <= maxMajor;
1654
+ }
1655
+ function checkPeerDeps(options = {}) {
1656
+ const { skipInProduction = true, logWarnings = true } = options;
1657
+ const result = {
1658
+ ok: true,
1659
+ warnings: [],
1660
+ errors: []
1661
+ };
1662
+ const isProduction = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
1663
+ if (skipInProduction && isProduction) {
1664
+ return result;
1665
+ }
1666
+ const currentWindow = globalThis.window;
1667
+ if (currentWindow === void 0) {
1668
+ return result;
1669
+ }
1670
+ const messages = getMessages();
1671
+ if (detectMultipleReactInstances()) {
1672
+ result.ok = false;
1673
+ result.errors.push(messages.MULTIPLE_REACT_INSTANCES);
1674
+ if (logWarnings) {
1675
+ console.error(messages.MULTIPLE_REACT_INSTANCES);
1676
+ }
1677
+ }
1678
+ const reactVersion = getPackageVersion("react");
1679
+ if (reactVersion) {
1680
+ if (!isVersionInRange(reactVersion, 18, 19)) {
1681
+ result.ok = false;
1682
+ const errorMsg = messages.UNSUPPORTED_REACT_VERSION(reactVersion);
1683
+ result.errors.push(errorMsg);
1684
+ if (logWarnings) {
1685
+ console.error(errorMsg);
1686
+ }
1687
+ }
1688
+ }
1689
+ const muiVersion = currentWindow["@mui/material"]?.version;
1690
+ if (muiVersion) {
1691
+ if (!isVersionInRange(muiVersion, 5, 7)) {
1692
+ result.warnings.push(messages.MUI_OUT_OF_RANGE(muiVersion));
1693
+ if (logWarnings) {
1694
+ logger.warn(messages.UNSUPPORTED_MUI_VERSION(muiVersion));
1254
1695
  }
1255
1696
  }
1256
1697
  }
@@ -1375,10 +1816,11 @@ function validateConsentProviderProps(props) {
1375
1816
 
1376
1817
  // src/utils/cookieDiscovery.ts
1377
1818
  function discoverRuntimeCookies() {
1378
- if (typeof document === "undefined" || !document.cookie) return [];
1819
+ const currentDocument = globalThis.document;
1820
+ if (currentDocument === void 0 || !currentDocument.cookie) return [];
1379
1821
  const names = Array.from(
1380
1822
  new Set(
1381
- document.cookie.split(";").map((s) => s.trim()).filter(Boolean).map((s) => s.split("=")[0])
1823
+ currentDocument.cookie.split(";").map((s) => s.trim()).filter(Boolean).map((s) => s.split("=")[0])
1382
1824
  )
1383
1825
  );
1384
1826
  const list = names.map((name) => ({ name }));
@@ -1389,27 +1831,34 @@ function discoverRuntimeCookies() {
1389
1831
  }
1390
1832
  return list;
1391
1833
  }
1834
+ function tryDecode(val) {
1835
+ try {
1836
+ return decodeURIComponent(val);
1837
+ } catch {
1838
+ return val;
1839
+ }
1840
+ }
1841
+ function isConsentJson(val) {
1842
+ if (!val.startsWith("{")) return false;
1843
+ try {
1844
+ const obj = JSON.parse(val);
1845
+ return obj && typeof obj === "object" && "preferences" in obj && "version" in obj;
1846
+ } catch {
1847
+ return false;
1848
+ }
1849
+ }
1392
1850
  function detectConsentCookieName() {
1393
- if (typeof document === "undefined" || !document.cookie) return null;
1851
+ const currentDocument = globalThis.document;
1852
+ if (currentDocument === void 0 || !currentDocument.cookie) return null;
1394
1853
  try {
1395
- const pairs = document.cookie.split(";").map((s) => s.trim()).filter(Boolean);
1854
+ const pairs = currentDocument.cookie.split(";").map((s) => s.trim()).filter(Boolean);
1396
1855
  for (const p of pairs) {
1397
1856
  const [name, ...rest] = p.split("=");
1398
1857
  const raw = rest.join("=");
1399
1858
  if (!raw) continue;
1400
- let val = raw;
1401
- try {
1402
- val = decodeURIComponent(raw);
1403
- } catch {
1404
- }
1405
- if (val.startsWith("{")) {
1406
- try {
1407
- const obj = JSON.parse(val);
1408
- if (obj && typeof obj === "object" && "preferences" in obj && "version" in obj) {
1409
- return name;
1410
- }
1411
- } catch {
1412
- }
1859
+ const val = tryDecode(raw);
1860
+ if (isConsentJson(val)) {
1861
+ return name;
1413
1862
  }
1414
1863
  }
1415
1864
  } catch {
@@ -1451,15 +1900,6 @@ function CategoriesProvider({
1451
1900
  disableDiscoveryLog
1452
1901
  }) {
1453
1902
  const [impliedVersion, setImpliedVersion] = React4.useState(0);
1454
- React4.useEffect(() => {
1455
- const handler = () => setImpliedVersion((v) => v + 1);
1456
- if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
1457
- window.addEventListener("lgpd:requiredCategories", handler);
1458
- return () => window.removeEventListener("lgpd:requiredCategories", handler);
1459
- }
1460
- return () => {
1461
- };
1462
- }, []);
1463
1903
  const contextValue = React4.useMemo(() => {
1464
1904
  const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
1465
1905
  const guidance = analyzeDeveloperConfiguration(config);
@@ -1471,35 +1911,47 @@ function CategoriesProvider({
1471
1911
  allCategories: guidance.activeCategoriesInfo
1472
1912
  };
1473
1913
  }, [config, impliedVersion]);
1914
+ React4.useEffect(() => {
1915
+ const currentWindow = globalThis.window;
1916
+ if (!currentWindow || typeof currentWindow.addEventListener !== "function") return;
1917
+ const handler = () => {
1918
+ setImpliedVersion((current) => current + 1);
1919
+ };
1920
+ currentWindow.addEventListener("lgpd:requiredCategories", handler);
1921
+ return () => {
1922
+ currentWindow.removeEventListener("lgpd:requiredCategories", handler);
1923
+ };
1924
+ }, []);
1474
1925
  React4.useEffect(() => {
1475
1926
  logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
1476
1927
  }, [contextValue.guidance, disableDeveloperGuidance]);
1477
1928
  React4.useEffect(() => {
1478
1929
  try {
1479
1930
  const gt = globalThis;
1480
- const env = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
1931
+ const env = gt.process?.env?.NODE_ENV;
1481
1932
  const isDev2 = env === "development";
1482
- if (!isDev2 || gt.__LGPD_DISCOVERY_LOGGED__ === true || disableDiscoveryLog) return;
1483
- const discovered = discoverRuntimeCookies();
1484
- const consentName = detectConsentCookieName() || DEFAULT_COOKIE_OPTS.name;
1485
- const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
1486
- if (typeof console !== "undefined") {
1487
- try {
1488
- console.group(`${PREFIX} \u{1F50E} Descoberta de cookies (experimental)`);
1489
- const names = Array.from(
1490
- new Set([consentName, ...discovered.map((d) => d.name)].filter(Boolean))
1491
- );
1492
- const rows = names.map((n) => ({ Cookie: n }));
1493
- if (typeof console.table === "function") console.table(rows);
1494
- else console.log(rows);
1495
- console.info(
1496
- `${PREFIX} \u2139\uFE0F Estes nomes s\xE3o detectados em tempo de execu\xE7\xE3o. Ajuste ou categorize via APIs de override se necess\xE1rio.`
1497
- );
1498
- console.groupEnd();
1499
- } catch {
1933
+ if (isDev2 && gt.__LGPD_DISCOVERY_LOGGED__ !== true && !disableDiscoveryLog) {
1934
+ const discovered = discoverRuntimeCookies();
1935
+ const consentName = detectConsentCookieName() || DEFAULT_COOKIE_OPTS.name;
1936
+ const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
1937
+ if (typeof console !== "undefined") {
1938
+ try {
1939
+ console.group(`${PREFIX} \u{1F50E} Descoberta de cookies (experimental)`);
1940
+ const names = Array.from(
1941
+ new Set([consentName, ...discovered.map((d) => d.name)].filter(Boolean))
1942
+ );
1943
+ const rows = names.map((n) => ({ Cookie: n }));
1944
+ if (typeof console.table === "function") console.table(rows);
1945
+ else console.log(rows);
1946
+ console.info(
1947
+ `${PREFIX} \u2139\uFE0F Estes nomes s\xE3o detectados em tempo de execu\xE7\xE3o. Ajuste ou categorize via APIs de override se necess\xE1rio.`
1948
+ );
1949
+ console.groupEnd();
1950
+ } catch {
1951
+ }
1500
1952
  }
1953
+ gt.__LGPD_DISCOVERY_LOGGED__ = true;
1501
1954
  }
1502
- gt.__LGPD_DISCOVERY_LOGGED__ = true;
1503
1955
  } catch {
1504
1956
  }
1505
1957
  }, [disableDiscoveryLog]);
@@ -1549,7 +2001,7 @@ function createFullConsentState(consented, preferences, source, projectConfig, i
1549
2001
  isModalOpen
1550
2002
  };
1551
2003
  }
1552
- var DEFAULT_TEXTS = {
2004
+ var BASE_TEXTS = {
1553
2005
  // Textos básicos
1554
2006
  bannerMessage: "Utilizamos cookies para melhorar sua experi\xEAncia.",
1555
2007
  acceptAll: "Aceitar todos",
@@ -1586,6 +2038,10 @@ var DEFAULT_TEXTS = {
1586
2038
  transferCountries: void 0
1587
2039
  // Exibido se definido
1588
2040
  };
2041
+ var DEFAULT_TEXTS = {
2042
+ ...BASE_TEXTS,
2043
+ ...EXPANDED_DEFAULT_TEXTS
2044
+ };
1589
2045
  function reducer(state, action) {
1590
2046
  logger.consentState(action.type, state);
1591
2047
  switch (action.type) {
@@ -1669,6 +2125,8 @@ function ConsentProvider({
1669
2125
  initialState,
1670
2126
  categories,
1671
2127
  texts: textsProp,
2128
+ language,
2129
+ textVariant,
1672
2130
  designTokens,
1673
2131
  PreferencesModalComponent,
1674
2132
  preferencesModalProps = {},
@@ -1693,7 +2151,11 @@ function ConsentProvider({
1693
2151
  onConsentChange,
1694
2152
  onAuditLog
1695
2153
  }) {
1696
- const texts = React4.useMemo(() => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }), [textsProp]);
2154
+ const mergedTexts = React4.useMemo(() => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }), [textsProp]);
2155
+ const texts = React4.useMemo(
2156
+ () => resolveTexts(mergedTexts, { language, variant: textVariant }),
2157
+ [mergedTexts, language, textVariant]
2158
+ );
1697
2159
  const cookie = React4.useMemo(() => {
1698
2160
  const base = { ...DEFAULT_COOKIE_OPTS, ...cookieOpts ?? {} };
1699
2161
  base.name = cookieOpts?.name ?? buildConsentStorageKey({
@@ -1706,6 +2168,13 @@ function ConsentProvider({
1706
2168
  return base;
1707
2169
  }, [cookieOpts, storage?.domain, storage?.namespace, storage?.version]);
1708
2170
  const consentVersion = storage?.version?.trim() || "1";
2171
+ React4.useEffect(() => {
2172
+ try {
2173
+ ;
2174
+ globalThis.__LGPD_CONSENT_COOKIE__ = cookie.name;
2175
+ } catch {
2176
+ }
2177
+ }, [cookie.name]);
1709
2178
  const finalCategoriesConfig = React4.useMemo(() => {
1710
2179
  const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
1711
2180
  if (!categories) return DEFAULT_PROJECT_CATEGORIES;
@@ -2068,51 +2537,100 @@ function ConsentGate(props) {
2068
2537
 
2069
2538
  // src/utils/scriptLoader.ts
2070
2539
  var LOADING_SCRIPTS = /* @__PURE__ */ new Map();
2071
- function loadScript(id, src, category = null, attrs = {}, nonce) {
2072
- if (typeof document === "undefined") return Promise.resolve();
2073
- if (document.getElementById(id)) return Promise.resolve();
2540
+ var DEFAULT_POLL_INTERVAL = 100;
2541
+ function resolveCookieNames(preferred) {
2542
+ const inferred = globalThis.__LGPD_CONSENT_COOKIE__ ?? null;
2543
+ const names = [preferred, inferred, "cookieConsent", "lgpd-consent__v1"].filter(
2544
+ Boolean
2545
+ );
2546
+ return Array.from(new Set(names));
2547
+ }
2548
+ function parseConsentFromCookie(names) {
2549
+ const raw = document.cookie;
2550
+ if (!raw) return null;
2551
+ const cookies = raw.split("; ").reduce((acc, part) => {
2552
+ const [k, ...rest] = part.split("=");
2553
+ acc[k] = rest.join("=");
2554
+ return acc;
2555
+ }, {});
2556
+ for (const name of names) {
2557
+ const value = cookies[name];
2558
+ if (!value) continue;
2559
+ try {
2560
+ const parsed = JSON.parse(decodeURIComponent(value));
2561
+ if (!parsed.consented || parsed.isModalOpen) continue;
2562
+ return parsed;
2563
+ } catch {
2564
+ continue;
2565
+ }
2566
+ }
2567
+ return null;
2568
+ }
2569
+ function hasCategoryConsent(snapshot, category) {
2570
+ if (!snapshot.consented || snapshot.isModalOpen) return false;
2571
+ if (category === null) return true;
2572
+ return Boolean(snapshot.preferences?.[category]);
2573
+ }
2574
+ function loadScript(id, src, category = null, attrs = {}, nonce, options) {
2575
+ const currentDocument = globalThis.document;
2576
+ if (!src || currentDocument === void 0) return Promise.resolve();
2577
+ if (currentDocument.getElementById(id)) return Promise.resolve();
2074
2578
  const existingPromise = LOADING_SCRIPTS.get(id);
2075
2579
  if (existingPromise) return existingPromise;
2580
+ const pollInterval = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL;
2581
+ const names = resolveCookieNames(options?.cookieName);
2582
+ const mergedAttrs = { ...attrs };
2076
2583
  const promise = new Promise((resolve, reject) => {
2584
+ const inject = () => {
2585
+ const s = currentDocument.createElement("script");
2586
+ s.id = id;
2587
+ s.src = src;
2588
+ s.async = mergedAttrs.async !== "false";
2589
+ const scriptNonce = mergedAttrs.nonce || nonce;
2590
+ if (scriptNonce) {
2591
+ s.nonce = scriptNonce;
2592
+ mergedAttrs.nonce = scriptNonce;
2593
+ }
2594
+ for (const [k, v] of Object.entries(mergedAttrs)) s.setAttribute(k, v);
2595
+ s.onload = () => {
2596
+ LOADING_SCRIPTS.delete(id);
2597
+ resolve();
2598
+ };
2599
+ s.onerror = () => {
2600
+ LOADING_SCRIPTS.delete(id);
2601
+ reject(new Error(`Failed to load script: ${src}`));
2602
+ };
2603
+ currentDocument.body.appendChild(s);
2604
+ };
2605
+ const snapshot = options?.consentSnapshot;
2606
+ const skipChecks = options?.skipConsentCheck === true;
2607
+ if (skipChecks) {
2608
+ inject();
2609
+ return;
2610
+ }
2611
+ if (snapshot) {
2612
+ if (!hasCategoryConsent(snapshot, category)) {
2613
+ reject(
2614
+ new Error(
2615
+ `Consent not granted for category '${category ?? "none"}' when attempting to load ${id}`
2616
+ )
2617
+ );
2618
+ return;
2619
+ }
2620
+ inject();
2621
+ return;
2622
+ }
2077
2623
  const checkConsent = () => {
2078
- const consentCookie = document.cookie.split("; ").find((row) => row.startsWith("cookieConsent="))?.split("=")[1];
2079
- if (!consentCookie) {
2080
- setTimeout(checkConsent, 100);
2624
+ const consent = parseConsentFromCookie(names);
2625
+ if (!consent) {
2626
+ setTimeout(checkConsent, pollInterval);
2081
2627
  return;
2082
2628
  }
2083
- try {
2084
- const consent = JSON.parse(decodeURIComponent(consentCookie));
2085
- if (!consent.consented || consent.isModalOpen) {
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);
2629
+ if (!hasCategoryConsent(consent, category)) {
2630
+ setTimeout(checkConsent, pollInterval);
2631
+ return;
2115
2632
  }
2633
+ inject();
2116
2634
  };
2117
2635
  checkConsent();
2118
2636
  });
@@ -2276,14 +2794,107 @@ function validateNecessaryClassification(integrations, enabledCategories) {
2276
2794
  }
2277
2795
 
2278
2796
  // src/utils/ConsentScriptLoader.tsx
2797
+ var scriptRegistry = /* @__PURE__ */ new Map();
2798
+ var queueListeners = /* @__PURE__ */ new Set();
2799
+ function notifyQueue() {
2800
+ queueListeners.forEach((listener) => {
2801
+ try {
2802
+ listener();
2803
+ } catch {
2804
+ }
2805
+ });
2806
+ }
2807
+ function subscribeQueue(listener) {
2808
+ queueListeners.add(listener);
2809
+ return () => {
2810
+ queueListeners.delete(listener);
2811
+ };
2812
+ }
2813
+ function createInternalScript(def) {
2814
+ return {
2815
+ ...def,
2816
+ status: "pending",
2817
+ lastAllowed: false,
2818
+ registeredAt: Date.now(),
2819
+ token: Date.now() + Math.random(),
2820
+ priority: def.priority ?? 0,
2821
+ allowReload: def.allowReload ?? false,
2822
+ onConsentUpdate: def.onConsentUpdate
2823
+ };
2824
+ }
2825
+ function registerScript(def) {
2826
+ const entry = createInternalScript(def);
2827
+ scriptRegistry.set(def.id, entry);
2828
+ notifyQueue();
2829
+ return () => {
2830
+ const current = scriptRegistry.get(def.id);
2831
+ if (current && current.token === entry.token) {
2832
+ scriptRegistry.delete(def.id);
2833
+ notifyQueue();
2834
+ }
2835
+ };
2836
+ }
2837
+ function getExecutableScripts(consent) {
2838
+ const allowedScripts = [];
2839
+ scriptRegistry.forEach((script) => {
2840
+ const categoryAllowed = script.category === "necessary" || consent.consented && Boolean(consent.preferences?.[script.category]);
2841
+ if (!categoryAllowed) {
2842
+ script.lastAllowed = false;
2843
+ return;
2844
+ }
2845
+ if (script.status === "running") return;
2846
+ if (script.status === "executed" && !script.allowReload) return;
2847
+ if (script.status === "executed" && script.allowReload && script.lastAllowed) return;
2848
+ script.lastAllowed = true;
2849
+ allowedScripts.push(script);
2850
+ });
2851
+ return allowedScripts.sort((a, b) => {
2852
+ if (a.category === "necessary" && b.category !== "necessary") return -1;
2853
+ if (b.category === "necessary" && a.category !== "necessary") return 1;
2854
+ if (a.category !== b.category) return a.category.localeCompare(b.category);
2855
+ if (a.priority !== b.priority) return (b.priority ?? 0) - (a.priority ?? 0);
2856
+ return a.registeredAt - b.registeredAt;
2857
+ });
2858
+ }
2859
+ async function processQueue(consent, devLogging) {
2860
+ const scripts = getExecutableScripts(consent);
2861
+ let order = 0;
2862
+ for (const script of scripts) {
2863
+ order += 1;
2864
+ script.status = "running";
2865
+ if (devLogging) {
2866
+ logger.info("[ConsentScriptLoader] executando script", {
2867
+ id: script.id,
2868
+ category: script.category,
2869
+ priority: script.priority ?? 0,
2870
+ order
2871
+ });
2872
+ }
2873
+ try {
2874
+ await Promise.resolve(script.execute());
2875
+ } catch (error) {
2876
+ logger.error(`\u274C Failed to execute script ${script.id}`, error);
2877
+ } finally {
2878
+ script.status = "executed";
2879
+ if (script.onConsentUpdate) {
2880
+ script.onConsentUpdate(consent);
2881
+ }
2882
+ }
2883
+ }
2884
+ }
2279
2885
  function ConsentScriptLoader({
2280
2886
  integrations,
2281
2887
  reloadOnChange = false,
2282
2888
  nonce
2283
2889
  }) {
2284
2890
  const { preferences, consented } = useConsent();
2891
+ const isHydrated = useConsentHydration();
2285
2892
  const categories = useCategories();
2286
- const loadedScripts = React4.useRef(/* @__PURE__ */ new Set());
2893
+ const [queueVersion, bumpQueueVersion] = React4.useState(0);
2894
+ React4.useEffect(() => {
2895
+ const unsubscribe = subscribeQueue(() => bumpQueueVersion((v) => v + 1));
2896
+ return unsubscribe;
2897
+ }, []);
2287
2898
  React4.useEffect(() => {
2288
2899
  try {
2289
2900
  const ids = (integrations || []).map((i) => i.id);
@@ -2344,15 +2955,44 @@ function ConsentScriptLoader({
2344
2955
  console.groupEnd();
2345
2956
  }
2346
2957
  }, [integrations, categories]);
2958
+ const processedIntegrationsRef = React4.useRef(/* @__PURE__ */ new Map());
2347
2959
  React4.useEffect(() => {
2348
- if (!consented) return;
2349
- const timeoutId = setTimeout(async () => {
2350
- for (const integration of integrations) {
2351
- const shouldLoad = preferences[integration.category];
2352
- const alreadyLoaded = loadedScripts.current.has(integration.id);
2353
- if (shouldLoad && (!alreadyLoaded || reloadOnChange)) {
2354
- try {
2355
- const mergedAttrs = integration.attrs ?? {};
2960
+ const cleanups = [];
2961
+ const currentIds = /* @__PURE__ */ new Set();
2962
+ integrations.forEach((integration) => {
2963
+ currentIds.add(integration.id);
2964
+ const structuralHash = JSON.stringify({
2965
+ category: integration.category,
2966
+ src: integration.src,
2967
+ priority: integration.priority,
2968
+ hasBootstrap: Boolean(integration.bootstrap),
2969
+ hasInit: Boolean(integration.init),
2970
+ hasOnConsentUpdate: Boolean(integration.onConsentUpdate)
2971
+ });
2972
+ const existingHash = processedIntegrationsRef.current.get(integration.id);
2973
+ if (existingHash === structuralHash && scriptRegistry.has(integration.id)) {
2974
+ return;
2975
+ }
2976
+ processedIntegrationsRef.current.set(integration.id, structuralHash);
2977
+ if (integration.bootstrap) {
2978
+ cleanups.push(
2979
+ registerScript({
2980
+ id: `${integration.id}__bootstrap`,
2981
+ category: "necessary",
2982
+ priority: (integration.priority ?? 0) + 1e3,
2983
+ execute: integration.bootstrap
2984
+ })
2985
+ );
2986
+ }
2987
+ cleanups.push(
2988
+ registerScript({
2989
+ id: integration.id,
2990
+ category: integration.category,
2991
+ priority: integration.priority,
2992
+ allowReload: reloadOnChange,
2993
+ onConsentUpdate: integration.onConsentUpdate,
2994
+ execute: async () => {
2995
+ const mergedAttrs = integration.attrs ? { ...integration.attrs } : {};
2356
2996
  const scriptNonce = integration.nonce ?? nonce;
2357
2997
  if (scriptNonce && !mergedAttrs.nonce) mergedAttrs.nonce = scriptNonce;
2358
2998
  await loadScript(
@@ -2360,26 +3000,54 @@ function ConsentScriptLoader({
2360
3000
  integration.src,
2361
3001
  integration.category,
2362
3002
  mergedAttrs,
2363
- scriptNonce
3003
+ scriptNonce,
3004
+ { skipConsentCheck: true }
2364
3005
  );
2365
3006
  if (integration.init) {
2366
3007
  integration.init();
2367
3008
  }
2368
- loadedScripts.current.add(integration.id);
2369
- } catch (error) {
2370
- logger.error(`\u274C Failed to load script: ${integration.id}`, error);
2371
3009
  }
3010
+ })
3011
+ );
3012
+ });
3013
+ processedIntegrationsRef.current.forEach((_, id) => {
3014
+ if (!currentIds.has(id)) {
3015
+ processedIntegrationsRef.current.delete(id);
3016
+ const script = scriptRegistry.get(id);
3017
+ if (script) {
3018
+ scriptRegistry.delete(id);
3019
+ }
3020
+ const bootstrapScript = scriptRegistry.get(`${id}__bootstrap`);
3021
+ if (bootstrapScript) {
3022
+ scriptRegistry.delete(`${id}__bootstrap`);
2372
3023
  }
2373
3024
  }
2374
- }, 0);
2375
- return () => clearTimeout(timeoutId);
2376
- }, [preferences, consented, integrations, reloadOnChange, nonce]);
3025
+ });
3026
+ return () => cleanups.forEach((fn) => fn());
3027
+ }, [integrations, reloadOnChange, nonce]);
3028
+ React4.useEffect(() => {
3029
+ if (!isHydrated) return;
3030
+ void processQueue({ consented, preferences }, process.env.NODE_ENV !== "production");
3031
+ }, [consented, preferences, isHydrated, queueVersion]);
3032
+ React4.useEffect(() => {
3033
+ if (!isHydrated) return;
3034
+ scriptRegistry.forEach((script) => {
3035
+ if (script.status !== "executed") return;
3036
+ if (typeof script.onConsentUpdate !== "function") return;
3037
+ script.onConsentUpdate({ consented, preferences });
3038
+ });
3039
+ }, [consented, preferences, isHydrated]);
2377
3040
  return null;
2378
3041
  }
2379
3042
  function useConsentScriptLoader() {
2380
3043
  const { preferences, consented } = useConsent();
3044
+ const isHydrated = useConsentHydration();
2381
3045
  return React4.useCallback(
2382
3046
  async (integration, nonce) => {
3047
+ if (!isHydrated) {
3048
+ logger.warn(`\u26A0\uFE0F Cannot load script ${integration.id}: Consent not hydrated yet`);
3049
+ return false;
3050
+ }
2383
3051
  if (!consented) {
2384
3052
  logger.warn(`\u26A0\uFE0F Cannot load script ${integration.id}: No consent given`);
2385
3053
  return false;
@@ -2400,7 +3068,11 @@ function useConsentScriptLoader() {
2400
3068
  integration.src,
2401
3069
  integration.category,
2402
3070
  mergedAttrs,
2403
- scriptNonce
3071
+ scriptNonce,
3072
+ {
3073
+ consentSnapshot: { consented, preferences },
3074
+ skipConsentCheck: true
3075
+ }
2404
3076
  );
2405
3077
  if (integration.init) {
2406
3078
  integration.init();
@@ -2411,16 +3083,129 @@ function useConsentScriptLoader() {
2411
3083
  return false;
2412
3084
  }
2413
3085
  },
2414
- [preferences, consented]
3086
+ [preferences, consented, isHydrated]
2415
3087
  );
2416
3088
  }
2417
3089
 
2418
3090
  // src/utils/scriptIntegrations.ts
3091
+ function createSuggestedIntegration(config) {
3092
+ const suggested = suggestCategoryForScript(config.id)[0] ?? "analytics";
3093
+ const category = resolveCategory(suggested, config.category);
3094
+ const { category: _ignored, ...rest } = config;
3095
+ return { ...rest, category };
3096
+ }
3097
+ var resolveCategory = (fallback, override) => {
3098
+ if (typeof override === "string" && override.trim().length > 0) return override.trim();
3099
+ return fallback;
3100
+ };
3101
+ var isDevEnv = () => {
3102
+ const env = typeof globalThis !== "undefined" ? globalThis.process?.env?.NODE_ENV : void 0;
3103
+ return env !== "production";
3104
+ };
3105
+ var resolveRequiredString = (value, field, integrationId) => {
3106
+ if (typeof value !== "string" || value.trim().length === 0) {
3107
+ if (isDevEnv()) {
3108
+ console.error(
3109
+ `[LGPD-CONSENT] Config inv\xE1lida: integra\xE7\xE3o "${integrationId}" requer "${field}".`
3110
+ );
3111
+ }
3112
+ return null;
3113
+ }
3114
+ return value.trim();
3115
+ };
3116
+ function buildConsentModeSignals(preferences) {
3117
+ const analytics = preferences.analytics ? "granted" : "denied";
3118
+ const marketing = preferences.marketing ? "granted" : "denied";
3119
+ return {
3120
+ ad_storage: marketing,
3121
+ ad_user_data: marketing,
3122
+ ad_personalization: marketing,
3123
+ analytics_storage: analytics
3124
+ };
3125
+ }
3126
+ function pushToLayer(entry, dataLayerName) {
3127
+ const currentWindow = globalThis.window;
3128
+ if (currentWindow === void 0) return;
3129
+ const registry = currentWindow;
3130
+ const name = dataLayerName ?? "dataLayer";
3131
+ const layer = registry[name] ?? [];
3132
+ registry[name] = layer;
3133
+ layer.push(entry);
3134
+ }
3135
+ function ensureGtag(dataLayerName = "dataLayer") {
3136
+ const currentWindow = globalThis.window;
3137
+ if (currentWindow === void 0) return null;
3138
+ const w = currentWindow;
3139
+ const registry = w;
3140
+ const layer = registry[dataLayerName] ?? [];
3141
+ registry[dataLayerName] = layer;
3142
+ if (typeof w.gtag !== "function") {
3143
+ const gtag = (...args) => {
3144
+ layer.push(args);
3145
+ };
3146
+ w.gtag = gtag;
3147
+ }
3148
+ return w.gtag;
3149
+ }
3150
+ function applyDefaultConsentMode(dataLayerName) {
3151
+ const payload = buildConsentModeSignals({
3152
+ analytics: false,
3153
+ marketing: false
3154
+ });
3155
+ const gtag = ensureGtag(dataLayerName);
3156
+ if (gtag) {
3157
+ gtag("consent", "default", payload);
3158
+ }
3159
+ pushToLayer(["consent", "default", payload], dataLayerName);
3160
+ }
3161
+ function applyConsentModeUpdate(preferences, dataLayerName) {
3162
+ const payload = buildConsentModeSignals(preferences);
3163
+ const gtag = ensureGtag(dataLayerName);
3164
+ if (gtag) {
3165
+ gtag("consent", "update", payload);
3166
+ }
3167
+ pushToLayer(["consent", "update", payload], dataLayerName);
3168
+ }
2419
3169
  function createGoogleAnalyticsIntegration(config) {
2420
- const src = config.scriptUrl ?? `https://www.googletagmanager.com/gtag/js?id=${config.measurementId}`;
3170
+ const category = resolveCategory("analytics", config.category);
3171
+ const measurementId = resolveRequiredString(
3172
+ config.measurementId,
3173
+ "measurementId",
3174
+ "google-analytics"
3175
+ );
3176
+ if (!measurementId) {
3177
+ return {
3178
+ id: "google-analytics",
3179
+ category,
3180
+ src: "",
3181
+ cookies: ["_ga", "_ga_*", "_gid"],
3182
+ cookiesInfo: [
3183
+ {
3184
+ name: "_ga",
3185
+ purpose: "Identifica\xE7\xE3o \xFAnica de visitantes para an\xE1lise de tr\xE1fego",
3186
+ duration: "2 anos",
3187
+ provider: "Google Analytics"
3188
+ },
3189
+ {
3190
+ name: "_ga_*",
3191
+ purpose: "Rastreamento de sess\xF5es e eventos espec\xEDficos do stream GA4",
3192
+ duration: "2 anos",
3193
+ provider: "Google Analytics"
3194
+ },
3195
+ {
3196
+ name: "_gid",
3197
+ purpose: "Distin\xE7\xE3o de visitantes \xFAnicos em per\xEDodo de 24h",
3198
+ duration: "24 horas",
3199
+ provider: "Google Analytics"
3200
+ }
3201
+ ],
3202
+ attrs: { async: "true" }
3203
+ };
3204
+ }
3205
+ const src = config.scriptUrl ?? `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
2421
3206
  return {
2422
3207
  id: "google-analytics",
2423
- category: "analytics",
3208
+ category,
2424
3209
  src,
2425
3210
  cookies: ["_ga", "_ga_*", "_gid"],
2426
3211
  cookiesInfo: [
@@ -2443,32 +3228,49 @@ function createGoogleAnalyticsIntegration(config) {
2443
3228
  provider: "Google Analytics"
2444
3229
  }
2445
3230
  ],
3231
+ bootstrap: () => {
3232
+ applyDefaultConsentMode();
3233
+ },
3234
+ onConsentUpdate: ({ preferences }) => {
3235
+ applyConsentModeUpdate(preferences);
3236
+ },
2446
3237
  init: () => {
2447
- if (globalThis.window !== void 0) {
2448
- const w = window;
2449
- w.dataLayer = w.dataLayer ?? [];
2450
- const gtag = (...args) => {
2451
- w.dataLayer.push(...args);
2452
- };
2453
- w.gtag = gtag;
2454
- gtag("js", /* @__PURE__ */ new Date());
2455
- gtag("config", config.measurementId, config.config ?? {});
2456
- }
3238
+ const gtag = ensureGtag();
3239
+ if (!gtag) return;
3240
+ gtag("js", /* @__PURE__ */ new Date());
3241
+ gtag("config", measurementId, config.config ?? {});
2457
3242
  },
2458
3243
  attrs: { async: "true" }
2459
3244
  };
2460
3245
  }
2461
3246
  function createGoogleTagManagerIntegration(config) {
2462
- const src = config.scriptUrl ?? `https://www.googletagmanager.com/gtm.js?id=${config.containerId}`;
3247
+ const category = resolveCategory("analytics", config.category);
3248
+ const containerId = resolveRequiredString(config.containerId, "containerId", "google-tag-manager");
3249
+ if (!containerId) {
3250
+ return {
3251
+ id: "google-tag-manager",
3252
+ category,
3253
+ src: "",
3254
+ cookies: ["_gcl_au"]
3255
+ };
3256
+ }
3257
+ const src = config.scriptUrl ?? `https://www.googletagmanager.com/gtm.js?id=${containerId}`;
2463
3258
  return {
2464
3259
  id: "google-tag-manager",
2465
- category: "analytics",
3260
+ category,
2466
3261
  src,
2467
3262
  cookies: ["_gcl_au"],
3263
+ bootstrap: () => {
3264
+ applyDefaultConsentMode(config.dataLayerName);
3265
+ },
3266
+ onConsentUpdate: ({ preferences }) => {
3267
+ applyConsentModeUpdate(preferences, config.dataLayerName);
3268
+ },
2468
3269
  init: () => {
2469
- if (globalThis.window !== void 0) {
3270
+ const currentWindow = globalThis.window;
3271
+ if (currentWindow !== void 0) {
2470
3272
  const dataLayerName = config.dataLayerName || "dataLayer";
2471
- const w = window;
3273
+ const w = currentWindow;
2472
3274
  const layer = w[dataLayerName] ?? [];
2473
3275
  w[dataLayerName] = layer;
2474
3276
  layer.push({ "gtm.start": Date.now(), event: "gtm.js" });
@@ -2477,20 +3279,31 @@ function createGoogleTagManagerIntegration(config) {
2477
3279
  };
2478
3280
  }
2479
3281
  function createUserWayIntegration(config) {
3282
+ const category = resolveCategory("functional", config.category);
3283
+ const accountId = resolveRequiredString(config.accountId, "accountId", "userway");
3284
+ if (!accountId) {
3285
+ return {
3286
+ id: "userway",
3287
+ category,
3288
+ src: "",
3289
+ cookies: ["_userway_*"]
3290
+ };
3291
+ }
2480
3292
  const src = config.scriptUrl ?? "https://cdn.userway.org/widget.js";
2481
3293
  return {
2482
3294
  id: "userway",
2483
- category: "functional",
3295
+ category,
2484
3296
  src,
2485
3297
  cookies: ["_userway_*"],
2486
3298
  init: () => {
2487
- if (globalThis.window !== void 0) {
2488
- const w = window;
3299
+ const currentWindow = globalThis.window;
3300
+ if (currentWindow !== void 0) {
3301
+ const w = currentWindow;
2489
3302
  w.UserWayWidgetApp = w.UserWayWidgetApp || {};
2490
- w.UserWayWidgetApp.accountId = config.accountId;
3303
+ w.UserWayWidgetApp.accountId = accountId;
2491
3304
  }
2492
3305
  },
2493
- attrs: { "data-account": config.accountId }
3306
+ attrs: { "data-account": accountId }
2494
3307
  };
2495
3308
  }
2496
3309
  var COMMON_INTEGRATIONS = {
@@ -2499,15 +3312,26 @@ var COMMON_INTEGRATIONS = {
2499
3312
  userway: createUserWayIntegration
2500
3313
  };
2501
3314
  function createFacebookPixelIntegration(config) {
3315
+ const category = resolveCategory("marketing", config.category);
3316
+ const pixelId = resolveRequiredString(config.pixelId, "pixelId", "facebook-pixel");
3317
+ if (!pixelId) {
3318
+ return {
3319
+ id: "facebook-pixel",
3320
+ category,
3321
+ src: "",
3322
+ cookies: ["_fbp", "fr"]
3323
+ };
3324
+ }
2502
3325
  const src = config.scriptUrl ?? "https://connect.facebook.net/en_US/fbevents.js";
2503
3326
  return {
2504
3327
  id: "facebook-pixel",
2505
- category: "marketing",
3328
+ category,
2506
3329
  src,
2507
3330
  cookies: ["_fbp", "fr"],
2508
3331
  init: () => {
2509
- if (globalThis.window !== void 0) {
2510
- const w = window;
3332
+ const currentWindow = globalThis.window;
3333
+ if (currentWindow !== void 0) {
3334
+ const w = currentWindow;
2511
3335
  if (!w.fbq) {
2512
3336
  const fbq = (...args) => {
2513
3337
  if (w.fbq && typeof w.fbq.callMethod === "function") {
@@ -2520,18 +3344,34 @@ function createFacebookPixelIntegration(config) {
2520
3344
  fbq.loaded = true;
2521
3345
  w.fbq = fbq;
2522
3346
  }
2523
- w.fbq("init", config.pixelId, config.advancedMatching ?? {});
3347
+ w.fbq("init", pixelId, config.advancedMatching ?? {});
2524
3348
  if (config.autoTrack !== false) w.fbq("track", "PageView");
2525
3349
  }
2526
3350
  }
2527
3351
  };
2528
3352
  }
2529
3353
  function createHotjarIntegration(config) {
3354
+ const category = resolveCategory("analytics", config.category);
3355
+ const siteId = resolveRequiredString(config.siteId, "siteId", "hotjar");
2530
3356
  const v = config.version ?? 6;
2531
- const src = config.scriptUrl ?? `https://static.hotjar.com/c/hotjar-${config.siteId}.js?sv=${v}`;
3357
+ if (!siteId) {
3358
+ return {
3359
+ id: "hotjar",
3360
+ category,
3361
+ src: "",
3362
+ cookies: [
3363
+ "_hjSession_*",
3364
+ "_hjSessionUser_*",
3365
+ "_hjFirstSeen",
3366
+ "_hjIncludedInSessionSample",
3367
+ "_hjAbsoluteSessionInProgress"
3368
+ ]
3369
+ };
3370
+ }
3371
+ const src = config.scriptUrl ?? `https://static.hotjar.com/c/hotjar-${siteId}.js?sv=${v}`;
2532
3372
  return {
2533
3373
  id: "hotjar",
2534
- category: "analytics",
3374
+ category,
2535
3375
  src,
2536
3376
  cookies: [
2537
3377
  "_hjSession_*",
@@ -2573,9 +3413,10 @@ function createHotjarIntegration(config) {
2573
3413
  }
2574
3414
  ],
2575
3415
  init: () => {
2576
- if (globalThis.window !== void 0) {
2577
- const w = window;
2578
- w._hjSettings = { hjid: config.siteId, hjsv: v };
3416
+ const currentWindow = globalThis.window;
3417
+ if (currentWindow !== void 0) {
3418
+ const w = currentWindow;
3419
+ w._hjSettings = { hjid: siteId, hjsv: v };
2579
3420
  if (!w.hj) {
2580
3421
  const hj = (...args) => {
2581
3422
  hj.q = hj.q || [];
@@ -2584,17 +3425,35 @@ function createHotjarIntegration(config) {
2584
3425
  w.hj = hj;
2585
3426
  }
2586
3427
  if (config.debug && typeof console !== "undefined" && typeof console.info === "function") {
2587
- console.info("[Hotjar] initialized with siteId", config.siteId);
3428
+ console.info("[Hotjar] initialized with siteId", siteId);
2588
3429
  }
2589
3430
  }
2590
3431
  }
2591
3432
  };
2592
3433
  }
2593
3434
  function createMixpanelIntegration(config) {
3435
+ const category = resolveCategory("analytics", config.category);
3436
+ const token = resolveRequiredString(config.token, "token", "mixpanel");
3437
+ if (!token) {
3438
+ return {
3439
+ id: "mixpanel",
3440
+ category,
3441
+ src: "",
3442
+ cookies: ["mp_*"],
3443
+ cookiesInfo: [
3444
+ {
3445
+ name: "mp_*",
3446
+ purpose: "Rastreamento de eventos e propriedades do usu\xE1rio para analytics",
3447
+ duration: "1 ano",
3448
+ provider: "Mixpanel"
3449
+ }
3450
+ ]
3451
+ };
3452
+ }
2594
3453
  const src = config.scriptUrl ?? "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";
2595
3454
  return {
2596
3455
  id: "mixpanel",
2597
- category: "analytics",
3456
+ category,
2598
3457
  src,
2599
3458
  cookies: ["mp_*"],
2600
3459
  cookiesInfo: [
@@ -2606,12 +3465,13 @@ function createMixpanelIntegration(config) {
2606
3465
  }
2607
3466
  ],
2608
3467
  init: () => {
2609
- if (globalThis.window !== void 0) {
2610
- const w = window;
3468
+ const currentWindow = globalThis.window;
3469
+ if (currentWindow !== void 0) {
3470
+ const w = currentWindow;
2611
3471
  w.mixpanel = w.mixpanel || { init: () => void 0 };
2612
3472
  if (w.mixpanel && typeof w.mixpanel.init === "function") {
2613
3473
  try {
2614
- w.mixpanel.init(config.token, config.config ?? {}, config.api_host);
3474
+ w.mixpanel.init(token, config.config ?? {}, config.api_host);
2615
3475
  } catch (error) {
2616
3476
  if (typeof console !== "undefined" && typeof console.warn === "function") {
2617
3477
  console.warn("[Mixpanel] Failed to initialize:", error);
@@ -2623,15 +3483,26 @@ function createMixpanelIntegration(config) {
2623
3483
  };
2624
3484
  }
2625
3485
  function createClarityIntegration(config) {
2626
- const src = config.scriptUrl ?? `https://www.clarity.ms/tag/${config.projectId}`;
3486
+ const category = resolveCategory("analytics", config.category);
3487
+ const projectId = resolveRequiredString(config.projectId, "projectId", "clarity");
3488
+ if (!projectId) {
3489
+ return {
3490
+ id: "clarity",
3491
+ category,
3492
+ src: "",
3493
+ cookies: ["_clck", "_clsk", "CLID", "ANONCHK", "MR", "MUID", "SM"]
3494
+ };
3495
+ }
3496
+ const src = config.scriptUrl ?? `https://www.clarity.ms/tag/${projectId}`;
2627
3497
  return {
2628
3498
  id: "clarity",
2629
- category: "analytics",
3499
+ category,
2630
3500
  src,
2631
3501
  cookies: ["_clck", "_clsk", "CLID", "ANONCHK", "MR", "MUID", "SM"],
2632
3502
  init: () => {
2633
- if (globalThis.window !== void 0 && typeof config.upload !== "undefined") {
2634
- const w = window;
3503
+ const currentWindow = globalThis.window;
3504
+ if (currentWindow !== void 0 && typeof config.upload !== "undefined") {
3505
+ const w = currentWindow;
2635
3506
  if (typeof w.clarity === "function") {
2636
3507
  try {
2637
3508
  w.clarity("set", "upload", config.upload);
@@ -2646,18 +3517,29 @@ function createClarityIntegration(config) {
2646
3517
  };
2647
3518
  }
2648
3519
  function createIntercomIntegration(config) {
2649
- const src = config.scriptUrl ?? `https://widget.intercom.io/widget/${config.app_id}`;
3520
+ const category = resolveCategory("functional", config.category);
3521
+ const appId = resolveRequiredString(config.app_id, "app_id", "intercom");
3522
+ if (!appId) {
3523
+ return {
3524
+ id: "intercom",
3525
+ category,
3526
+ src: "",
3527
+ cookies: ["intercom-id-*", "intercom-session-*"]
3528
+ };
3529
+ }
3530
+ const src = config.scriptUrl ?? `https://widget.intercom.io/widget/${appId}`;
2650
3531
  return {
2651
3532
  id: "intercom",
2652
- category: "functional",
3533
+ category,
2653
3534
  src,
2654
3535
  cookies: ["intercom-id-*", "intercom-session-*"],
2655
3536
  init: () => {
2656
- if (globalThis.window !== void 0) {
2657
- const w = window;
3537
+ const currentWindow = globalThis.window;
3538
+ if (currentWindow !== void 0) {
3539
+ const w = currentWindow;
2658
3540
  if (typeof w.Intercom === "function") {
2659
3541
  try {
2660
- w.Intercom("boot", { app_id: config.app_id });
3542
+ w.Intercom("boot", { app_id: appId });
2661
3543
  } catch (error) {
2662
3544
  if (typeof console !== "undefined" && typeof console.warn === "function") {
2663
3545
  console.warn("[Intercom] Failed to boot:", error);
@@ -2669,18 +3551,29 @@ function createIntercomIntegration(config) {
2669
3551
  };
2670
3552
  }
2671
3553
  function createZendeskChatIntegration(config) {
2672
- const src = config.scriptUrl ?? `https://static.zdassets.com/ekr/snippet.js?key=${config.key}`;
3554
+ const category = resolveCategory("functional", config.category);
3555
+ const key = resolveRequiredString(config.key, "key", "zendesk-chat");
3556
+ if (!key) {
3557
+ return {
3558
+ id: "zendesk-chat",
3559
+ category,
3560
+ src: "",
3561
+ cookies: ["__zlcmid", "_zendesk_shared_session"]
3562
+ };
3563
+ }
3564
+ const src = config.scriptUrl ?? `https://static.zdassets.com/ekr/snippet.js?key=${key}`;
2673
3565
  return {
2674
3566
  id: "zendesk-chat",
2675
- category: "functional",
3567
+ category,
2676
3568
  src,
2677
3569
  cookies: ["__zlcmid", "_zendesk_shared_session"],
2678
3570
  init: () => {
2679
- if (globalThis.window !== void 0) {
2680
- const w = window;
3571
+ const currentWindow = globalThis.window;
3572
+ if (currentWindow !== void 0) {
3573
+ const w = currentWindow;
2681
3574
  if (typeof w.zE === "function") {
2682
3575
  try {
2683
- w.zE("webWidget", "identify", { key: config.key });
3576
+ w.zE("webWidget", "identify", { key });
2684
3577
  } catch (error) {
2685
3578
  if (typeof console !== "undefined" && typeof console.warn === "function") {
2686
3579
  console.warn("[Zendesk] Failed to identify:", error);
@@ -2802,215 +3695,4 @@ function createAnpdCategoriesConfig(options = {}) {
2802
3695
  };
2803
3696
  }
2804
3697
 
2805
- // src/types/advancedTexts.ts
2806
- var EXPANDED_DEFAULT_TEXTS = {
2807
- // Textos adicionais
2808
- confirm: "Confirmar",
2809
- cancel: "Cancelar",
2810
- loading: "Carregando...",
2811
- // Feedback
2812
- feedback: {
2813
- saveSuccess: "Prefer\xEAncias salvas com sucesso!",
2814
- saveError: "Erro ao salvar prefer\xEAncias. Tente novamente.",
2815
- consentUpdated: "Consentimento atualizado.",
2816
- cookiesRejected: "Cookies opcionais rejeitados.",
2817
- settingsReset: "Configura\xE7\xF5es resetadas."
2818
- },
2819
- // Acessibilidade
2820
- accessibility: {
2821
- bannerLabel: "Banner de consentimento de cookies",
2822
- modalLabel: "Modal de prefer\xEAncias de cookies",
2823
- keyboardNavigation: "Use Tab para navegar, Enter para selecionar",
2824
- toggleState: {
2825
- enabled: "Habilitado",
2826
- disabled: "Desabilitado"
2827
- },
2828
- liveRegion: "Regi\xE3o de an\xFAncios din\xE2micos"
2829
- },
2830
- // Categorias
2831
- categories: {
2832
- necessary: {
2833
- name: "Cookies Necess\xE1rios",
2834
- description: "Essenciais para o funcionamento b\xE1sico do site",
2835
- examples: "Sess\xE3o, seguran\xE7a, prefer\xEAncias de idioma"
2836
- },
2837
- analytics: {
2838
- name: "Cookies de Analytics",
2839
- description: "Ajudam a entender como os visitantes usam o site",
2840
- examples: "Google Analytics, contadores de p\xE1gina"
2841
- },
2842
- marketing: {
2843
- name: "Cookies de Marketing",
2844
- description: "Usados para personalizar an\xFAncios e ofertas",
2845
- examples: "Facebook Pixel, Google Ads, remarketing"
2846
- },
2847
- functional: {
2848
- name: "Cookies Funcionais",
2849
- description: "Melhoram a funcionalidade e personaliza\xE7\xE3o",
2850
- examples: "Chat, mapas, v\xEDdeos embarcados"
2851
- },
2852
- performance: {
2853
- name: "Cookies de Performance",
2854
- description: "Coletam informa\xE7\xF5es sobre velocidade e estabilidade",
2855
- examples: "Monitoramento de erro, otimiza\xE7\xE3o de velocidade"
2856
- }
2857
- },
2858
- // Contextos específicos
2859
- contexts: {
2860
- ecommerce: {
2861
- cartAbandonment: "Lembramos dos produtos no seu carrinho",
2862
- personalizedOffers: "Ofertas personalizadas baseadas no seu hist\xF3rico",
2863
- paymentSecurity: "Seguran\xE7a adicional no processo de pagamento",
2864
- productRecommendations: "Sugest\xF5es de produtos relevantes"
2865
- },
2866
- saas: {
2867
- userAnalytics: "An\xE1lise de uso para melhorar funcionalidades",
2868
- performanceMonitoring: "Monitoramento de performance da aplica\xE7\xE3o",
2869
- featureUsage: "Estat\xEDsticas de uso de recursos",
2870
- customerSupport: "Suporte ao cliente mais eficiente"
2871
- },
2872
- government: {
2873
- citizenServices: "Melhoria dos servi\xE7os ao cidad\xE3o",
2874
- dataProtection: "Prote\xE7\xE3o rigorosa dos dados pessoais",
2875
- transparency: "Transpar\xEAncia no uso de dados",
2876
- accessibility: "Recursos de acessibilidade digital"
2877
- },
2878
- education: {
2879
- studentProgress: "Acompanhamento do progresso educacional",
2880
- learningAnalytics: "Analytics para melhorar o aprendizado",
2881
- accessibility: "Recursos educacionais acess\xEDveis",
2882
- parentalConsent: "Consentimento parental quando necess\xE1rio"
2883
- }
2884
- },
2885
- // Variações de tom
2886
- variants: {
2887
- formal: {
2888
- bannerMessage: "Este s\xEDtio eletr\xF4nico utiliza cookies para otimizar a experi\xEAncia de navega\xE7\xE3o.",
2889
- acceptAll: "Concordar com todos os cookies",
2890
- declineAll: "Recusar cookies opcionais",
2891
- modalTitle: "Configura\xE7\xE3o de Cookies"
2892
- },
2893
- casual: {
2894
- bannerMessage: "\u{1F36A} Ei! Usamos cookies para tornar sua experi\xEAncia ainda melhor!",
2895
- acceptAll: "Aceitar tudo",
2896
- declineAll: "S\xF3 o essencial",
2897
- modalTitle: "Seus Cookies"
2898
- },
2899
- concise: {
2900
- bannerMessage: "Usamos cookies. Voc\xEA aceita?",
2901
- acceptAll: "Sim",
2902
- declineAll: "N\xE3o",
2903
- modalTitle: "Cookies"
2904
- },
2905
- detailed: {
2906
- bannerMessage: "Utilizamos cookies e tecnologias similares para melhorar sua experi\xEAncia de navega\xE7\xE3o, personalizar conte\xFAdo, analisar tr\xE1fego e oferecer funcionalidades de redes sociais.",
2907
- acceptAll: "Aceitar todos os cookies e tecnologias",
2908
- declineAll: "Recusar todos os cookies opcionais",
2909
- modalTitle: "Centro de Prefer\xEAncias de Privacidade"
2910
- }
2911
- },
2912
- // Internacionalização simplificada (apenas textos básicos)
2913
- i18n: {
2914
- en: {
2915
- bannerMessage: "We use cookies to enhance your experience.",
2916
- acceptAll: "Accept All",
2917
- declineAll: "Decline",
2918
- preferences: "Preferences",
2919
- modalTitle: "Cookie Preferences",
2920
- modalIntro: "Customize your cookie preferences below.",
2921
- save: "Save Preferences",
2922
- necessaryAlwaysOn: "Necessary cookies (always active)"
2923
- },
2924
- es: {
2925
- bannerMessage: "Utilizamos cookies para mejorar su experiencia.",
2926
- acceptAll: "Aceptar Todo",
2927
- declineAll: "Rechazar",
2928
- preferences: "Preferencias",
2929
- modalTitle: "Preferencias de Cookies",
2930
- modalIntro: "Personalice sus preferencias de cookies a continuaci\xF3n.",
2931
- save: "Guardar Preferencias",
2932
- necessaryAlwaysOn: "Cookies necess\xE1rias (sempre ativas)"
2933
- },
2934
- fr: {
2935
- bannerMessage: "Nous utilisons des cookies pour am\xE9liorer votre exp\xE9rience.",
2936
- acceptAll: "Tout Accepter",
2937
- declineAll: "Refuser",
2938
- preferences: "Pr\xE9f\xE9rences",
2939
- modalTitle: "Pr\xE9f\xE9rences des Cookies",
2940
- modalIntro: "Personnalisez vos pr\xE9f\xE9rences de cookies ci-dessous.",
2941
- save: "Enregistrer les Pr\xE9f\xE9rences",
2942
- necessaryAlwaysOn: "Cookies n\xE9cessaires (toujours actifs)"
2943
- }
2944
- },
2945
- // Textos técnicos
2946
- technical: {
2947
- sessionCookies: "Cookies de sess\xE3o s\xE3o tempor\xE1rios e expiram quando voc\xEA fecha o navegador.",
2948
- persistentCookies: "Cookies persistentes permanecem no seu dispositivo at\xE9 expirarem ou serem removidos.",
2949
- thirdPartyCookies: "Cookies de terceiros s\xE3o definidos por dom\xEDnios diferentes do site que voc\xEA est\xE1 visitando.",
2950
- browserSettings: "Voc\xEA pode gerenciar cookies nas configura\xE7\xF5es do seu navegador.",
2951
- disablingImpact: "Desabilitar cookies pode afetar a funcionalidade do site."
2952
- },
2953
- // Cookie details
2954
- cookieDetails: {
2955
- tableHeaders: {
2956
- name: "Nome",
2957
- purpose: "Finalidade",
2958
- duration: "Dura\xE7\xE3o",
2959
- provider: "Fornecedor",
2960
- type: "Tipo"
2961
- },
2962
- noCookies: "Nenhum cookie encontrado para esta categoria.",
2963
- toggleDetails: {
2964
- expand: "Ver detalhes",
2965
- collapse: "Ocultar detalhes"
2966
- }
2967
- }
2968
- };
2969
- function resolveTexts(texts, options = {}) {
2970
- const { language = "pt", variant } = options;
2971
- let resolved = { ...texts };
2972
- if (variant && texts.variants?.[variant]) {
2973
- resolved = { ...resolved, ...texts.variants[variant] };
2974
- }
2975
- if (language !== "pt" && texts.i18n?.[language]) {
2976
- resolved = { ...resolved, ...texts.i18n[language] };
2977
- }
2978
- return resolved;
2979
- }
2980
- var TEXT_TEMPLATES = {
2981
- ecommerce: {
2982
- ...EXPANDED_DEFAULT_TEXTS,
2983
- bannerMessage: "Utilizamos cookies para personalizar ofertas e melhorar sua experi\xEAncia de compra.",
2984
- acceptAll: "Aceitar e continuar",
2985
- variants: {
2986
- casual: {
2987
- bannerMessage: "\u{1F6D2} Usamos cookies para encontrar as melhores ofertas para voc\xEA!",
2988
- acceptAll: "Quero ofertas personalizadas!"
2989
- }
2990
- }
2991
- },
2992
- saas: {
2993
- ...EXPANDED_DEFAULT_TEXTS,
2994
- bannerMessage: "Utilizamos cookies para otimizar o desempenho da aplica\xE7\xE3o e sua experi\xEAncia.",
2995
- acceptAll: "Aceitar e otimizar",
2996
- variants: {
2997
- formal: {
2998
- bannerMessage: "Esta aplica\xE7\xE3o utiliza cookies para an\xE1lise de performance e melhoria cont\xEDnua da experi\xEAncia do usu\xE1rio.",
2999
- acceptAll: "Autorizar coleta de dados de uso"
3000
- }
3001
- }
3002
- },
3003
- government: {
3004
- ...EXPANDED_DEFAULT_TEXTS,
3005
- bannerMessage: "Este portal utiliza cookies em conformidade com a LGPD para melhorar os servi\xE7os p\xFAblicos.",
3006
- acceptAll: "Aceitar em conformidade",
3007
- variants: {
3008
- formal: {
3009
- bannerMessage: "Este s\xEDtio eletr\xF4nico do governo utiliza cookies estritamente necess\xE1rios e opcionais, em conformidade com a Lei Geral de Prote\xE7\xE3o de Dados.",
3010
- acceptAll: "Concordar com o uso de cookies"
3011
- }
3012
- }
3013
- }
3014
- };
3015
-
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 };
3698
+ 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, createSuggestedIntegration, 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 };