react-lgpd-consent 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  // src/components/PreferencesModal.tsx
2
+ import Box2 from "@mui/material/Box";
2
3
  import Button2 from "@mui/material/Button";
3
4
  import Dialog from "@mui/material/Dialog";
4
5
  import DialogActions from "@mui/material/DialogActions";
@@ -8,194 +9,262 @@ import FormControlLabel from "@mui/material/FormControlLabel";
8
9
  import FormGroup from "@mui/material/FormGroup";
9
10
  import Switch from "@mui/material/Switch";
10
11
  import Typography3 from "@mui/material/Typography";
11
- import { useEffect as useEffect3, useState as useState2 } from "react";
12
+ import { useEffect as useEffect3, useState as useState3 } from "react";
12
13
 
13
14
  // src/context/CategoriesContext.tsx
14
15
  import * as React2 from "react";
15
16
 
16
- // src/utils/developerGuidance.ts
17
- import React from "react";
18
- var DEFAULT_PROJECT_CATEGORIES = {
19
- enabledCategories: ["analytics"]
17
+ // src/utils/cookieRegistry.ts
18
+ var COOKIE_PATTERNS_BY_CATEGORY = {
19
+ necessary: ["cookieConsent"],
20
+ analytics: ["_ga", "_ga_*", "_gid", "_gcl_au", "_hj*", "mp_*", "_clck", "_clsk"],
21
+ functional: ["intercom-*", "__zlcmid", "_zendesk_shared_session", "_userway_*"],
22
+ marketing: ["_fbp", "fr"],
23
+ social: [],
24
+ personalization: []
20
25
  };
21
- function analyzeDeveloperConfiguration(config) {
22
- const guidance = {
23
- warnings: [],
24
- suggestions: [],
25
- activeCategoriesInfo: [],
26
- usingDefaults: !config
27
- };
28
- const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
29
- if (!config) {
30
- guidance.warnings.push(
31
- 'LGPD-CONSENT: Nenhuma configura\xE7\xE3o de categorias especificada. Usando padr\xE3o: necessary + analytics. Para produ\xE7\xE3o, recomenda-se especificar explicitamente as categorias via prop "categories".'
32
- );
33
- }
34
- guidance.activeCategoriesInfo.push({
35
- id: "necessary",
36
- name: "Cookies Necess\xE1rios",
37
- description: "Essenciais para funcionamento b\xE1sico do site",
38
- essential: true,
39
- uiRequired: false
40
- });
41
- const enabledCategories = finalConfig.enabledCategories || [];
42
- const categoryNames = {
43
- analytics: {
44
- name: "Cookies Anal\xEDticos",
45
- description: "Medem uso e performance do site"
26
+ var COOKIE_INFO_BY_INTEGRATION = {
27
+ "google-analytics": [
28
+ {
29
+ name: "_ga",
30
+ purpose: "Identifica\xE7\xE3o \xFAnica de visitantes para an\xE1lise de tr\xE1fego",
31
+ duration: "2 anos",
32
+ provider: "Google Analytics"
46
33
  },
47
- functional: {
48
- name: "Cookies Funcionais",
49
- description: "Melhoram experi\xEAncia e funcionalidades"
34
+ {
35
+ name: "_ga_*",
36
+ purpose: "Rastreamento de sess\xF5es e eventos espec\xEDficos do stream GA4",
37
+ duration: "2 anos",
38
+ provider: "Google Analytics"
50
39
  },
51
- marketing: {
52
- name: "Cookies de Marketing",
53
- description: "Publicidade direcionada e campanhas"
40
+ {
41
+ name: "_gid",
42
+ purpose: "Distin\xE7\xE3o de visitantes \xFAnicos em per\xEDodo de 24h",
43
+ duration: "24 horas",
44
+ provider: "Google Analytics"
45
+ }
46
+ ],
47
+ "google-tag-manager": [
48
+ {
49
+ name: "_gcl_au",
50
+ purpose: "Rastreamento de convers\xF5es de an\xFAncios",
51
+ duration: "90 dias",
52
+ provider: "Google"
53
+ }
54
+ ],
55
+ hotjar: [
56
+ {
57
+ name: "_hjSession_*",
58
+ purpose: "Rastreamento de sess\xE3o",
59
+ duration: "30 minutos",
60
+ provider: "Hotjar"
54
61
  },
55
- social: {
56
- name: "Cookies de Redes Sociais",
57
- description: "Integra\xE7\xE3o com plataformas sociais"
62
+ {
63
+ name: "_hjSessionUser_*",
64
+ purpose: "Persist\xEAncia de usu\xE1rio entre sess\xF5es",
65
+ duration: "365 dias",
66
+ provider: "Hotjar"
58
67
  },
59
- personalization: {
60
- name: "Cookies de Personaliza\xE7\xE3o",
61
- description: "Adaptam conte\xFAdo \xE0s prefer\xEAncias do usu\xE1rio"
68
+ {
69
+ name: "_hjFirstSeen",
70
+ purpose: "Detec\xE7\xE3o da primeira visita do usu\xE1rio",
71
+ duration: "Sess\xE3o",
72
+ provider: "Hotjar"
62
73
  }
63
- };
64
- enabledCategories.forEach((categoryId) => {
65
- const categoryInfo = categoryNames[categoryId];
66
- if (categoryInfo) {
67
- guidance.activeCategoriesInfo.push({
68
- id: categoryId,
69
- name: categoryInfo.name,
70
- description: categoryInfo.description,
71
- essential: false,
72
- uiRequired: true
73
- });
74
+ ],
75
+ mixpanel: [
76
+ {
77
+ name: "mp_*",
78
+ purpose: "Rastreamento de eventos e propriedades do usu\xE1rio para analytics",
79
+ duration: "1 ano",
80
+ provider: "Mixpanel"
74
81
  }
75
- });
76
- const custom = finalConfig.customCategories || [];
77
- custom.forEach((cat) => {
78
- if (!cat?.id || cat.id === "necessary") return;
79
- guidance.activeCategoriesInfo.push({
80
- id: cat.id,
81
- name: cat.name,
82
- description: cat.description,
83
- essential: !!cat.essential,
84
- uiRequired: !cat.essential
82
+ ],
83
+ clarity: [
84
+ {
85
+ name: "_clck",
86
+ purpose: "Identificador de usu\xE1rio",
87
+ duration: "365 dias",
88
+ provider: "Microsoft"
89
+ },
90
+ { name: "_clsk", purpose: "Rastreamento de sess\xE3o", duration: "1 dia", provider: "Microsoft" }
91
+ ],
92
+ intercom: [
93
+ {
94
+ name: "intercom-id-*",
95
+ purpose: "Identificador do usu\xE1rio",
96
+ duration: "9 meses",
97
+ provider: "Intercom"
98
+ },
99
+ {
100
+ name: "intercom-session-*",
101
+ purpose: "Gerenciamento de sess\xE3o",
102
+ duration: "1 semana",
103
+ provider: "Intercom"
104
+ }
105
+ ],
106
+ "zendesk-chat": [
107
+ {
108
+ name: "__zlcmid",
109
+ purpose: "Identificador de sess\xE3o de chat",
110
+ duration: "1 ano",
111
+ provider: "Zendesk"
112
+ },
113
+ {
114
+ name: "_zendesk_shared_session",
115
+ purpose: "Gerenciamento de sess\xE3o",
116
+ duration: "Sess\xE3o",
117
+ provider: "Zendesk"
118
+ }
119
+ ],
120
+ userway: [
121
+ {
122
+ name: "_userway_*",
123
+ purpose: "Prefer\xEAncias de acessibilidade",
124
+ duration: "1 ano",
125
+ provider: "UserWay"
126
+ }
127
+ ],
128
+ "facebook-pixel": [
129
+ { name: "_fbp", purpose: "Rastreamento de an\xFAncios", duration: "90 dias", provider: "Meta" },
130
+ { name: "fr", purpose: "Direcionamento de an\xFAncios", duration: "90 dias", provider: "Meta" }
131
+ ]
132
+ };
133
+ var INTEGRATION_DEFAULT_CATEGORY = {
134
+ "google-analytics": "analytics",
135
+ "google-tag-manager": "analytics",
136
+ hotjar: "analytics",
137
+ mixpanel: "analytics",
138
+ clarity: "analytics",
139
+ intercom: "functional",
140
+ "zendesk-chat": "functional",
141
+ userway: "functional",
142
+ "facebook-pixel": "marketing"
143
+ };
144
+ var COOKIE_CATALOG_OVERRIDES = {};
145
+ var COOKIE_CATEGORY_OVERRIDES = {};
146
+ function setCookieCatalogOverrides(overrides) {
147
+ COOKIE_CATALOG_OVERRIDES = {
148
+ byCategory: { ...COOKIE_CATALOG_OVERRIDES.byCategory || {}, ...overrides.byCategory || {} },
149
+ byIntegration: {
150
+ ...COOKIE_CATALOG_OVERRIDES.byIntegration || {},
151
+ ...overrides.byIntegration || {}
152
+ }
153
+ };
154
+ }
155
+ function setCookieCategoryOverrides(map) {
156
+ COOKIE_CATEGORY_OVERRIDES = { ...COOKIE_CATEGORY_OVERRIDES, ...map };
157
+ }
158
+ function matchPattern(name, pattern) {
159
+ if (pattern.endsWith("*")) return name.startsWith(pattern.slice(0, -1));
160
+ return name === pattern;
161
+ }
162
+ function getCookiesInfoForCategory(categoryId, usedIntegrations) {
163
+ const result = [];
164
+ usedIntegrations.forEach((id) => {
165
+ const defaultCat = INTEGRATION_DEFAULT_CATEGORY[id];
166
+ const defaults = COOKIE_INFO_BY_INTEGRATION[id] || [];
167
+ const list = COOKIE_CATALOG_OVERRIDES.byIntegration?.[id] || defaults;
168
+ list.forEach((desc) => {
169
+ const overrideCat = Object.entries(COOKIE_CATEGORY_OVERRIDES).find(
170
+ ([pattern]) => matchPattern(desc.name, pattern)
171
+ )?.[1];
172
+ const finalCat = overrideCat ?? defaultCat;
173
+ if (finalCat === categoryId && !result.find((d) => d.name === desc.name)) result.push(desc);
85
174
  });
86
175
  });
87
- const totalToggleable = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
88
- if (totalToggleable === 0) {
89
- guidance.suggestions.push(
90
- 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance completo LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.'
91
- );
176
+ const catOverride = COOKIE_CATALOG_OVERRIDES.byCategory?.[categoryId];
177
+ if (catOverride) {
178
+ catOverride.forEach((d) => {
179
+ const idx = result.findIndex((x) => x.name === d.name);
180
+ if (idx >= 0) result[idx] = d;
181
+ else result.push(d);
182
+ });
92
183
  }
93
- if (totalToggleable > 5) {
94
- guidance.warnings.push(
95
- `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode prejudicar experi\xEAncia do usu\xE1rio. Considere agrupar categorias similares.`
96
- );
184
+ if (categoryId === "necessary") {
185
+ if (!result.find((d) => d.name === "cookieConsent")) {
186
+ result.push({
187
+ name: "cookieConsent",
188
+ purpose: "Armazena suas prefer\xEAncias de consentimento",
189
+ duration: "365 dias",
190
+ provider: "Este site"
191
+ });
192
+ }
97
193
  }
98
- return guidance;
194
+ return result;
99
195
  }
100
- function logDeveloperGuidance(guidance, disableGuidanceProp) {
101
- const gt = globalThis;
102
- const nodeEnv = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
103
- const isProd = nodeEnv === "production" || gt.__LGPD_PRODUCTION__ === true;
104
- const isDisabled = !!disableGuidanceProp || gt.__LGPD_DISABLE_GUIDANCE__ === true;
105
- if (isProd || isDisabled) return;
106
- const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
107
- if (guidance.warnings.length > 0) {
108
- console.group(`${PREFIX} \u26A0\uFE0F Avisos de Configura\xE7\xE3o`);
109
- guidance.warnings.forEach((msg) => console.warn(`${PREFIX} ${msg}`));
110
- console.groupEnd();
111
- }
112
- if (guidance.suggestions.length > 0) {
113
- console.group(`${PREFIX} \u{1F4A1} Sugest\xF5es`);
114
- guidance.suggestions.forEach((msg) => console.info(`${PREFIX} ${msg}`));
115
- console.groupEnd();
116
- }
117
- if (guidance.usingDefaults) {
118
- console.warn(
119
- `${PREFIX} \u{1F4CB} Usando configura\xE7\xE3o padr\xE3o. Para personalizar, use a prop "categories" no ConsentProvider.`
120
- );
121
- }
122
- const rows = guidance.activeCategoriesInfo.map((cat) => ({
123
- ID: cat.id,
124
- Nome: cat.name,
125
- "Toggle UI?": cat.uiRequired ? "\u2705 SIM" : "\u274C N\xC3O (sempre ativo)",
126
- "Essencial?": cat.essential ? "\u{1F512} SIM" : "\u2699\uFE0F N\xC3O"
127
- }));
128
- if (typeof console.table === "function") {
129
- console.group(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`);
130
- console.table(rows);
131
- console.info(`${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`);
132
- console.groupEnd();
133
- } else {
134
- console.log(`${PREFIX} \u{1F527} Categorias Ativas (para UI customizada)`, rows);
135
- console.info(`${PREFIX} \u2139\uFE0F Use estes dados para criar componentes customizados adequados.`);
196
+
197
+ // src/utils/cookieDiscovery.ts
198
+ function discoverRuntimeCookies() {
199
+ if (typeof document === "undefined" || !document.cookie) return [];
200
+ const names = Array.from(
201
+ new Set(
202
+ document.cookie.split(";").map((s) => s.trim()).filter(Boolean).map((s) => s.split("=")[0])
203
+ )
204
+ );
205
+ const list = names.map((name) => ({ name }));
206
+ try {
207
+ ;
208
+ globalThis.__LGPD_DISCOVERED_COOKIES__ = list;
209
+ } catch {
136
210
  }
211
+ return list;
137
212
  }
138
- function useDeveloperGuidance(config, disableGuidanceProp) {
139
- const guidance = React.useMemo(() => {
140
- return analyzeDeveloperConfiguration(config);
141
- }, [config]);
142
- React.useEffect(() => {
143
- if (!disableGuidanceProp) {
144
- logDeveloperGuidance(guidance, disableGuidanceProp);
213
+ function detectConsentCookieName() {
214
+ if (typeof document === "undefined" || !document.cookie) return null;
215
+ try {
216
+ const pairs = document.cookie.split(";").map((s) => s.trim()).filter(Boolean);
217
+ for (const p of pairs) {
218
+ const [name, ...rest] = p.split("=");
219
+ const raw = rest.join("=");
220
+ if (!raw) continue;
221
+ let val = raw;
222
+ try {
223
+ val = decodeURIComponent(raw);
224
+ } catch {
225
+ }
226
+ if (val.startsWith("{")) {
227
+ try {
228
+ const obj = JSON.parse(val);
229
+ if (obj && typeof obj === "object" && "preferences" in obj && "version" in obj) {
230
+ return name;
231
+ }
232
+ } catch {
233
+ }
234
+ }
145
235
  }
146
- }, [guidance, disableGuidanceProp]);
147
- return guidance;
148
- }
149
-
150
- // src/context/CategoriesContext.tsx
151
- import { jsx } from "react/jsx-runtime";
152
- var CategoriesContext = React2.createContext(null);
153
- function CategoriesProvider({
154
- children,
155
- config,
156
- disableDeveloperGuidance
157
- }) {
158
- const contextValue = React2.useMemo(() => {
159
- const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
160
- const guidance = analyzeDeveloperConfiguration(config);
161
- const toggleableCategories = guidance.activeCategoriesInfo.filter((cat) => cat.uiRequired);
162
- return {
163
- config: finalConfig,
164
- guidance,
165
- toggleableCategories,
166
- allCategories: guidance.activeCategoriesInfo
167
- };
168
- }, [config]);
169
- React2.useEffect(() => {
170
- logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
171
- }, [contextValue.guidance, disableDeveloperGuidance]);
172
- return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
173
- }
174
- function useCategories() {
175
- const context = React2.useContext(CategoriesContext);
176
- if (!context) {
177
- throw new Error(
178
- "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
179
- );
236
+ } catch {
180
237
  }
181
- return context;
238
+ return null;
182
239
  }
183
- function useCategoryStatus(categoryId) {
184
- const { allCategories } = useCategories();
185
- const category = allCategories.find((cat) => cat.id === categoryId);
186
- return {
187
- isActive: !!category,
188
- isEssential: category?.essential || false,
189
- needsToggle: category?.uiRequired || false,
190
- name: category?.name,
191
- description: category?.description
192
- };
240
+ function categorizeDiscoveredCookies(discovered, registerOverrides = false) {
241
+ const list = discovered || globalThis.__LGPD_DISCOVERED_COOKIES__ || [];
242
+ const out = {};
243
+ function matchPattern2(name, pattern) {
244
+ if (pattern.endsWith("*")) return name.startsWith(pattern.slice(0, -1));
245
+ return name === pattern;
246
+ }
247
+ list.filter((d) => d.name && d.name !== "cookieConsent").forEach((d) => {
248
+ let assigned = null;
249
+ Object.keys(COOKIE_PATTERNS_BY_CATEGORY).forEach((cat2) => {
250
+ if (assigned) return;
251
+ const patterns = COOKIE_PATTERNS_BY_CATEGORY[cat2] || [];
252
+ if (patterns.some((p) => matchPattern2(d.name, p))) assigned = cat2;
253
+ });
254
+ const cat = assigned || "analytics";
255
+ out[cat] = out[cat] || [];
256
+ if (!out[cat].find((x) => x.name === d.name)) out[cat].push(d);
257
+ });
258
+ if (registerOverrides) {
259
+ const byCategory = {};
260
+ Object.entries(out).forEach(([cat, cookies]) => {
261
+ byCategory[cat] = cookies;
262
+ });
263
+ setCookieCatalogOverrides({ byCategory });
264
+ }
265
+ return out;
193
266
  }
194
267
 
195
- // src/context/ConsentContext.tsx
196
- import * as React4 from "react";
197
- import { ThemeProvider } from "@mui/material/styles";
198
-
199
268
  // src/utils/cookieUtils.ts
200
269
  import Cookies from "js-cookie";
201
270
 
@@ -466,6 +535,478 @@ function removeConsentCookie(opts) {
466
535
  logger.info("Consent cookie removed");
467
536
  }
468
537
 
538
+ // src/utils/developerGuidance.ts
539
+ import React from "react";
540
+ var DEFAULT_PROJECT_CATEGORIES = {
541
+ enabledCategories: ["analytics"]
542
+ };
543
+ function calculateComplianceScore(guidance) {
544
+ let score = 0;
545
+ const maxScore = 100;
546
+ if (!guidance.usingDefaults) score += 30;
547
+ const totalCategories = guidance.activeCategoriesInfo.length;
548
+ const toggleableCategories = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
549
+ if (totalCategories > 1) score += 20;
550
+ if (toggleableCategories >= 2 && toggleableCategories <= 4) score += 25;
551
+ const criticalWarnings = guidance.messages.filter((m) => m.severity === "error").length;
552
+ const warnings = guidance.messages.filter((m) => m.severity === "warning").length;
553
+ if (criticalWarnings === 0) score += 15;
554
+ if (warnings === 0) score += 10;
555
+ return Math.min(score, maxScore);
556
+ }
557
+ function analyzeDeveloperConfiguration(config) {
558
+ const guidance = {
559
+ warnings: [],
560
+ suggestions: [],
561
+ messages: [],
562
+ activeCategoriesInfo: [],
563
+ usingDefaults: !config,
564
+ complianceScore: 0
565
+ };
566
+ const addMessage = (severity, message, category, actionable = true) => {
567
+ const guidanceMessage = { severity, message, category, actionable };
568
+ guidance.messages.push(guidanceMessage);
569
+ if (severity === "warning" || severity === "error") {
570
+ guidance.warnings.push(message);
571
+ } else {
572
+ guidance.suggestions.push(message);
573
+ }
574
+ };
575
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
576
+ if (!config) {
577
+ addMessage(
578
+ "warning",
579
+ 'LGPD-CONSENT: Nenhuma configura\xE7\xE3o de categorias especificada. Usando padr\xE3o: necessary + analytics. Para produ\xE7\xE3o, especifique explicitamente as categorias via prop "categories".',
580
+ "configuration"
581
+ );
582
+ }
583
+ guidance.activeCategoriesInfo.push({
584
+ id: "necessary",
585
+ name: "Cookies Necess\xE1rios",
586
+ description: "Essenciais para funcionamento b\xE1sico do site",
587
+ essential: true,
588
+ uiRequired: false,
589
+ cookies: COOKIE_PATTERNS_BY_CATEGORY["necessary"]
590
+ });
591
+ const enabled = finalConfig.enabledCategories || [];
592
+ const NAMES = {
593
+ analytics: { name: "Cookies Anal\xEDticos", description: "Medem uso e performance do site" },
594
+ functional: {
595
+ name: "Cookies Funcionais",
596
+ description: "Melhoram experi\xEAncia e funcionalidades"
597
+ },
598
+ marketing: { name: "Cookies de Marketing", description: "Publicidade direcionada e campanhas" },
599
+ social: { name: "Cookies de Redes Sociais", description: "Integra\xE7\xE3o com plataformas sociais" },
600
+ personalization: { name: "Cookies de Personaliza\xE7\xE3o", description: "Adapta\xE7\xE3o de conte\xFAdo" }
601
+ };
602
+ enabled.forEach((id) => {
603
+ const info = NAMES[id];
604
+ if (info) {
605
+ guidance.activeCategoriesInfo.push({
606
+ id,
607
+ name: info.name,
608
+ description: info.description,
609
+ essential: false,
610
+ uiRequired: true,
611
+ cookies: COOKIE_PATTERNS_BY_CATEGORY[id]
612
+ });
613
+ }
614
+ });
615
+ const custom = finalConfig.customCategories || [];
616
+ custom.forEach((cat) => {
617
+ if (!cat?.id || cat.id === "necessary") return;
618
+ guidance.activeCategoriesInfo.push({
619
+ id: cat.id,
620
+ name: cat.name,
621
+ description: cat.description,
622
+ essential: !!cat.essential,
623
+ uiRequired: !cat.essential,
624
+ cookies: cat.cookies
625
+ });
626
+ });
627
+ try {
628
+ const gt = globalThis;
629
+ const implied = (gt.__LGPD_REQUIRED_CATEGORIES__ || []).filter(Boolean);
630
+ implied.forEach((id) => {
631
+ if (!guidance.activeCategoriesInfo.find((c) => c.id === id)) {
632
+ const info = NAMES[id];
633
+ if (info) {
634
+ guidance.activeCategoriesInfo.push({
635
+ id,
636
+ name: info.name,
637
+ description: info.description,
638
+ essential: false,
639
+ uiRequired: true,
640
+ cookies: COOKIE_PATTERNS_BY_CATEGORY[id]
641
+ });
642
+ if (!enabled.includes(id)) {
643
+ addMessage(
644
+ "info",
645
+ `Integra\xE7\xF5es detectadas requerem a categoria '${id}'. Adicione-a em categories.enabledCategories.`,
646
+ "integration"
647
+ );
648
+ }
649
+ }
650
+ }
651
+ });
652
+ } catch {
653
+ }
654
+ try {
655
+ const gt2 = globalThis;
656
+ const used = gt2.__LGPD_USED_INTEGRATIONS__ || [];
657
+ guidance.activeCategoriesInfo = guidance.activeCategoriesInfo.map((c) => {
658
+ const info = getCookiesInfoForCategory(c.id, used);
659
+ const names = Array.from(/* @__PURE__ */ new Set([...c.cookies || [], ...info.map((d) => d.name)]));
660
+ return { ...c, cookies: names };
661
+ });
662
+ } catch {
663
+ }
664
+ const totalToggleable = guidance.activeCategoriesInfo.filter((c) => c.uiRequired).length;
665
+ if (totalToggleable === 0) {
666
+ addMessage(
667
+ "info",
668
+ 'Apenas cookies necess\xE1rios est\xE3o configurados. Para compliance LGPD, considere adicionar categorias como "analytics" ou "functional" conforme uso real.',
669
+ "compliance"
670
+ );
671
+ }
672
+ if (totalToggleable > 5) {
673
+ addMessage(
674
+ "warning",
675
+ `${totalToggleable} categorias opcionais detectadas. UI com muitas op\xE7\xF5es pode prejudicar a experi\xEAncia. Considere agrupar categorias similares.`,
676
+ "usability"
677
+ );
678
+ }
679
+ guidance.complianceScore = calculateComplianceScore(guidance);
680
+ return guidance;
681
+ }
682
+ var GUIDANCE_CACHE = /* @__PURE__ */ new Set();
683
+ var SESSION_LOGGED = {
684
+ intro: false,
685
+ bestPractices: false
686
+ };
687
+ function getComplianceScoreColor(score) {
688
+ if (score >= 80) return "#4caf50";
689
+ if (score >= 60) return "#ff9800";
690
+ return "#f44336";
691
+ }
692
+ function logComplianceScore(prefix, score) {
693
+ const color = getComplianceScoreColor(score);
694
+ console.log(
695
+ `%c${prefix} Score de Conformidade LGPD: ${score}/100`,
696
+ `color: ${color}; font-weight: bold; font-size: 14px;`
697
+ );
698
+ }
699
+ function logMessagesByType(prefix, messages, type, config) {
700
+ const filteredMessages = messages.filter((m) => m.severity === type);
701
+ if (filteredMessages.length === 0) return false;
702
+ const typeConfig = {
703
+ error: {
704
+ show: config.showWarnings,
705
+ title: "Erros Cr\xEDticos",
706
+ color: "#d32f2f",
707
+ method: console.error
708
+ },
709
+ warning: {
710
+ show: config.showWarnings,
711
+ title: "Avisos de Configura\xE7\xE3o",
712
+ color: "#f57c00",
713
+ method: console.warn
714
+ },
715
+ info: {
716
+ show: config.showSuggestions,
717
+ title: "Sugest\xF5es",
718
+ color: "#2196f3",
719
+ method: console.info
720
+ }
721
+ };
722
+ const typeSettings = typeConfig[type];
723
+ if (!typeSettings.show) return false;
724
+ console.group(
725
+ `%c${prefix} ${typeSettings.title}`,
726
+ `color: ${typeSettings.color}; font-weight: bold;`
727
+ );
728
+ filteredMessages.forEach(
729
+ (msg) => typeSettings.method(
730
+ `%c${prefix}%c ${msg.message}`,
731
+ `color: ${typeSettings.color};`,
732
+ "color: #333;"
733
+ )
734
+ );
735
+ console.groupEnd();
736
+ return true;
737
+ }
738
+ function getGuidanceHash(guidance) {
739
+ const sortedWarnings = [...guidance.warnings].sort((a, b) => a.localeCompare(b));
740
+ const sortedSuggestions = [...guidance.suggestions].sort(
741
+ (a, b) => a.localeCompare(b)
742
+ );
743
+ const sortedCategories = guidance.activeCategoriesInfo.map((c) => c.id).sort((a, b) => a.localeCompare(b));
744
+ return JSON.stringify({
745
+ warnings: sortedWarnings,
746
+ suggestions: sortedSuggestions,
747
+ categories: sortedCategories,
748
+ usingDefaults: guidance.usingDefaults
749
+ });
750
+ }
751
+ function logIntroOnce() {
752
+ if (SESSION_LOGGED.intro) return;
753
+ SESSION_LOGGED.intro = true;
754
+ console.log(
755
+ `%c\u{1F36A} LGPD-CONSENT %c- Sistema de Consentimento Ativo`,
756
+ "background: #4caf50; color: white; padding: 4px 8px; border-radius: 4px; font-weight: bold;",
757
+ "color: #2e7d32; font-weight: 500;"
758
+ );
759
+ }
760
+ function logServerSideIfAvailable(guidance) {
761
+ try {
762
+ const gt = globalThis;
763
+ if (gt.process?.stdout?.write) {
764
+ const prefix = "\x1B[36m[LGPD-CONSENT]\x1B[0m";
765
+ const warnings = guidance.warnings.length;
766
+ const suggestions = guidance.suggestions.length;
767
+ const stdout = gt.process.stdout;
768
+ if (warnings > 0 || suggestions > 0) {
769
+ stdout.write(`${prefix} \u{1F527} Config: ${warnings} avisos, ${suggestions} sugest\xF5es
770
+ `);
771
+ if (warnings > 0) {
772
+ guidance.warnings.forEach((w) => {
773
+ stdout.write(`${prefix} \x1B[33m\u26A0\uFE0F ${w}\x1B[0m
774
+ `);
775
+ });
776
+ }
777
+ if (suggestions > 0) {
778
+ guidance.suggestions.forEach((s) => {
779
+ stdout.write(`${prefix} \x1B[36m\u{1F4A1} ${s}\x1B[0m
780
+ `);
781
+ });
782
+ }
783
+ }
784
+ }
785
+ } catch {
786
+ }
787
+ }
788
+ function logDeveloperGuidance(guidance, disableGuidanceProp, config) {
789
+ const gt = globalThis;
790
+ const nodeEnv = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
791
+ const isProd = nodeEnv === "production" || gt.__LGPD_PRODUCTION__ === true;
792
+ if (isProd || disableGuidanceProp) return;
793
+ const guidanceHash = getGuidanceHash(guidance);
794
+ if (GUIDANCE_CACHE.has(guidanceHash)) return;
795
+ GUIDANCE_CACHE.add(guidanceHash);
796
+ logServerSideIfAvailable(guidance);
797
+ const guidanceConfig = {
798
+ showWarnings: true,
799
+ showSuggestions: true,
800
+ showCategoriesTable: true,
801
+ showBestPractices: true,
802
+ showComplianceScore: true,
803
+ minimumSeverity: "info",
804
+ ...config
805
+ };
806
+ if (guidanceConfig.messageProcessor) {
807
+ guidanceConfig.messageProcessor(guidance.messages);
808
+ return;
809
+ }
810
+ logIntroOnce();
811
+ const PREFIX = "\u{1F36A}";
812
+ let hasImportantInfo = false;
813
+ const filteredMessages = guidance.messages.filter((msg) => {
814
+ const severityLevels = { info: 0, warning: 1, error: 2 };
815
+ const minLevel = severityLevels[guidanceConfig.minimumSeverity || "info"];
816
+ const msgLevel = severityLevels[msg.severity];
817
+ return msgLevel >= minLevel;
818
+ });
819
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "error", guidanceConfig) || hasImportantInfo;
820
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "warning", guidanceConfig) || hasImportantInfo;
821
+ if (hasImportantInfo || guidance.usingDefaults) {
822
+ hasImportantInfo = logMessagesByType(PREFIX, filteredMessages, "info", guidanceConfig) || hasImportantInfo;
823
+ }
824
+ if (guidanceConfig.showComplianceScore && guidance.complianceScore !== void 0) {
825
+ logComplianceScore(PREFIX, guidance.complianceScore);
826
+ }
827
+ if (guidanceConfig.showCategoriesTable && (hasImportantInfo || guidance.usingDefaults)) {
828
+ const rows = guidance.activeCategoriesInfo.map((cat) => ({
829
+ "\u{1F4CA} Categoria": cat.id,
830
+ "\u{1F3F7}\uFE0F Nome": cat.name,
831
+ "\u{1F39B}\uFE0F UI": cat.uiRequired ? "\u2705" : "\u{1F512}",
832
+ "\u{1F36A} Cookies": (cat.cookies || []).slice(0, 3).join(", ") + (cat.cookies && cat.cookies.length > 3 ? ` (+${cat.cookies.length - 3})` : "")
833
+ }));
834
+ if (typeof console.table === "function") {
835
+ console.group(`%c${PREFIX} Configura\xE7\xE3o Ativa`, "color: #4caf50; font-weight: bold;");
836
+ console.table(rows);
837
+ console.groupEnd();
838
+ }
839
+ }
840
+ if (!SESSION_LOGGED.bestPractices && hasImportantInfo) {
841
+ SESSION_LOGGED.bestPractices = true;
842
+ console.group(`%c${PREFIX} LGPD - Boas Pr\xE1ticas`, "color: #9c27b0; font-weight: bold;");
843
+ console.info(
844
+ `%c${PREFIX}%c Necessary: sempre ativo \u2022 Demais: opt-out por padr\xE3o`,
845
+ "color: #9c27b0;",
846
+ "color: #7b1fa2;"
847
+ );
848
+ console.info(
849
+ `%c${PREFIX}%c Documente pol\xEDticas claras por categoria`,
850
+ "color: #9c27b0;",
851
+ "color: #7b1fa2;"
852
+ );
853
+ console.info(
854
+ `%c${PREFIX}%c Registre consentimento com data/hora/origem`,
855
+ "color: #9c27b0;",
856
+ "color: #7b1fa2;"
857
+ );
858
+ console.groupEnd();
859
+ }
860
+ }
861
+ function useDeveloperGuidance(config, disableGuidanceProp, guidanceConfig) {
862
+ const guidance = React.useMemo(() => analyzeDeveloperConfiguration(config), [config]);
863
+ React.useEffect(() => {
864
+ if (!disableGuidanceProp) logDeveloperGuidance(guidance, disableGuidanceProp, guidanceConfig);
865
+ }, [guidance, disableGuidanceProp, guidanceConfig]);
866
+ return guidance;
867
+ }
868
+ var GUIDANCE_PRESETS = {
869
+ /** Configuração completa para desenvolvimento */
870
+ development: {
871
+ showWarnings: true,
872
+ showSuggestions: true,
873
+ showCategoriesTable: true,
874
+ showBestPractices: true,
875
+ showComplianceScore: true,
876
+ minimumSeverity: "info"
877
+ },
878
+ /** Configuração silenciosa para produção */
879
+ production: {
880
+ showWarnings: false,
881
+ showSuggestions: false,
882
+ showCategoriesTable: false,
883
+ showBestPractices: false,
884
+ showComplianceScore: false,
885
+ minimumSeverity: "error"
886
+ },
887
+ /** Apenas erros críticos */
888
+ minimal: {
889
+ showWarnings: true,
890
+ showSuggestions: false,
891
+ showCategoriesTable: false,
892
+ showBestPractices: false,
893
+ showComplianceScore: false,
894
+ minimumSeverity: "error"
895
+ },
896
+ /** Focado em conformidade LGPD */
897
+ compliance: {
898
+ showWarnings: true,
899
+ showSuggestions: true,
900
+ showCategoriesTable: true,
901
+ showBestPractices: true,
902
+ showComplianceScore: true,
903
+ minimumSeverity: "warning"
904
+ }
905
+ };
906
+
907
+ // src/context/CategoriesContext.tsx
908
+ import { jsx } from "react/jsx-runtime";
909
+ var CategoriesContext = React2.createContext(null);
910
+ function CategoriesProvider({
911
+ children,
912
+ config,
913
+ disableDeveloperGuidance,
914
+ disableDiscoveryLog
915
+ }) {
916
+ const [impliedVersion, setImpliedVersion] = React2.useState(0);
917
+ React2.useEffect(() => {
918
+ const handler = () => setImpliedVersion((v) => v + 1);
919
+ if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
920
+ window.addEventListener("lgpd:requiredCategories", handler);
921
+ return () => window.removeEventListener("lgpd:requiredCategories", handler);
922
+ }
923
+ return () => {
924
+ };
925
+ }, []);
926
+ const contextValue = React2.useMemo(() => {
927
+ const finalConfig = config || DEFAULT_PROJECT_CATEGORIES;
928
+ const guidance = analyzeDeveloperConfiguration(config);
929
+ const toggleableCategories = guidance.activeCategoriesInfo.filter((cat) => cat.uiRequired);
930
+ return {
931
+ config: finalConfig,
932
+ guidance,
933
+ toggleableCategories,
934
+ allCategories: guidance.activeCategoriesInfo
935
+ };
936
+ }, [config, impliedVersion]);
937
+ React2.useEffect(() => {
938
+ logDeveloperGuidance(contextValue.guidance, disableDeveloperGuidance);
939
+ }, [contextValue.guidance, disableDeveloperGuidance]);
940
+ React2.useEffect(() => {
941
+ try {
942
+ const gt = globalThis;
943
+ const env = typeof gt.process !== "undefined" ? gt.process?.env?.NODE_ENV : void 0;
944
+ const isDev = env === "development";
945
+ if (!isDev || gt.__LGPD_DISCOVERY_LOGGED__ === true || disableDiscoveryLog) return;
946
+ const discovered = discoverRuntimeCookies();
947
+ const consentName = detectConsentCookieName() || DEFAULT_COOKIE_OPTS.name;
948
+ const PREFIX = "[\u{1F36A} LGPD-CONSENT]";
949
+ if (typeof console !== "undefined") {
950
+ try {
951
+ console.group(`${PREFIX} \u{1F50E} Descoberta de cookies (experimental)`);
952
+ const names = Array.from(
953
+ new Set([consentName, ...discovered.map((d) => d.name)].filter(Boolean))
954
+ );
955
+ const rows = names.map((n) => ({ Cookie: n }));
956
+ if (typeof console.table === "function") console.table(rows);
957
+ else console.log(rows);
958
+ console.info(
959
+ `${PREFIX} \u2139\uFE0F Estes nomes s\xE3o detectados em tempo de execu\xE7\xE3o. Ajuste ou categorize via APIs de override se necess\xE1rio.`
960
+ );
961
+ console.groupEnd();
962
+ } catch {
963
+ }
964
+ }
965
+ gt.__LGPD_DISCOVERY_LOGGED__ = true;
966
+ } catch {
967
+ }
968
+ }, [disableDiscoveryLog]);
969
+ return /* @__PURE__ */ jsx(CategoriesContext.Provider, { value: contextValue, children });
970
+ }
971
+ function useCategories() {
972
+ const context = React2.useContext(CategoriesContext);
973
+ if (!context) {
974
+ throw new Error(
975
+ "useCategories deve ser usado dentro de CategoriesProvider. Certifique-se de que o ConsentProvider est\xE1 envolvendo seu componente."
976
+ );
977
+ }
978
+ return context;
979
+ }
980
+ function useCategoryStatus(categoryId) {
981
+ const { allCategories } = useCategories();
982
+ const category = allCategories.find((cat) => cat.id === categoryId);
983
+ return {
984
+ isActive: !!category,
985
+ isEssential: category?.essential || false,
986
+ needsToggle: category?.uiRequired || false,
987
+ name: category?.name,
988
+ description: category?.description
989
+ };
990
+ }
991
+
992
+ // src/context/DesignContext.tsx
993
+ import * as React3 from "react";
994
+ import { jsx as jsx2 } from "react/jsx-runtime";
995
+ var DesignContext = React3.createContext(void 0);
996
+ function DesignProvider({
997
+ tokens,
998
+ children
999
+ }) {
1000
+ return /* @__PURE__ */ jsx2(DesignContext.Provider, { value: tokens, children });
1001
+ }
1002
+ function useDesignTokens() {
1003
+ return React3.useContext(DesignContext);
1004
+ }
1005
+
1006
+ // src/context/ConsentContext.tsx
1007
+ import { ThemeProvider } from "@mui/material/styles";
1008
+ import * as React4 from "react";
1009
+
469
1010
  // src/utils/categoryUtils.ts
470
1011
  function createProjectPreferences(config, defaultValue = false) {
471
1012
  const preferences = {
@@ -478,8 +1019,8 @@ function createProjectPreferences(config, defaultValue = false) {
478
1019
  preferences[category] = defaultValue;
479
1020
  }
480
1021
  });
481
- const custom = config?.customCategories || [];
482
- custom.forEach((cat) => {
1022
+ const customCategories = config?.customCategories || [];
1023
+ customCategories.forEach((cat) => {
483
1024
  if (cat.id && cat.id !== "necessary") {
484
1025
  preferences[cat.id] = defaultValue;
485
1026
  }
@@ -497,8 +1038,8 @@ function validateProjectPreferences(preferences, config) {
497
1038
  validPreferences[category] = preferences[category];
498
1039
  }
499
1040
  });
500
- const custom = config?.customCategories || [];
501
- custom.forEach((cat) => {
1041
+ const customCategories = config?.customCategories || [];
1042
+ customCategories.forEach((cat) => {
502
1043
  const id = cat.id;
503
1044
  if (id && id !== "necessary" && preferences[id] !== void 0) {
504
1045
  validPreferences[id] = preferences[id];
@@ -521,8 +1062,8 @@ function getAllProjectCategories(config) {
521
1062
  allCategories.push(getDefaultCategoryDefinition(category));
522
1063
  }
523
1064
  });
524
- const custom = config?.customCategories || [];
525
- custom.forEach((cat) => {
1065
+ const customCategories = config?.customCategories || [];
1066
+ customCategories.forEach((cat) => {
526
1067
  if (cat.id && cat.id !== "necessary") {
527
1068
  allCategories.push({ ...cat, essential: !!cat.essential });
528
1069
  }
@@ -571,20 +1112,6 @@ function getDefaultCategoryDefinition(category) {
571
1112
  return definitions[category];
572
1113
  }
573
1114
 
574
- // src/context/DesignContext.tsx
575
- import * as React3 from "react";
576
- import { jsx as jsx2 } from "react/jsx-runtime";
577
- var DesignContext = React3.createContext(void 0);
578
- function DesignProvider({
579
- tokens,
580
- children
581
- }) {
582
- return /* @__PURE__ */ jsx2(DesignContext.Provider, { value: tokens, children });
583
- }
584
- function useDesignTokens() {
585
- return React3.useContext(DesignContext);
586
- }
587
-
588
1115
  // src/components/CookieBanner.tsx
589
1116
  import Button from "@mui/material/Button";
590
1117
  import Box from "@mui/material/Box";
@@ -661,6 +1188,7 @@ function Branding({ variant, hidden = false }) {
661
1188
  import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
662
1189
  function CookieBanner({
663
1190
  policyLinkUrl,
1191
+ termsLinkUrl,
664
1192
  debug,
665
1193
  blocking = true,
666
1194
  hideBranding = false,
@@ -680,15 +1208,15 @@ function CookieBanner({
680
1208
  hideBranding
681
1209
  });
682
1210
  if (!open) return null;
683
- const bannerStyle = {
1211
+ const bannerStyle = (theme) => ({
684
1212
  p: designTokens?.spacing?.padding?.banner ?? 2,
685
1213
  maxWidth: 720,
686
1214
  mx: "auto",
687
- backgroundColor: designTokens?.colors?.background,
688
- color: designTokens?.colors?.text,
1215
+ backgroundColor: designTokens?.colors?.background ?? theme.palette.background?.paper,
1216
+ color: designTokens?.colors?.text ?? theme.palette.text?.primary,
689
1217
  borderRadius: designTokens?.spacing?.borderRadius?.banner,
690
1218
  fontFamily: designTokens?.typography?.fontFamily
691
- };
1219
+ });
692
1220
  const bannerContent = /* @__PURE__ */ jsx4(Paper, { elevation: 3, sx: bannerStyle, ...PaperProps, children: /* @__PURE__ */ jsxs2(Stack, { spacing: 1, children: [
693
1221
  /* @__PURE__ */ jsxs2(Typography2, { variant: "body2", sx: { fontSize: designTokens?.typography?.fontSize?.banner }, children: [
694
1222
  texts.bannerMessage,
@@ -754,27 +1282,51 @@ function CookieBanner({
754
1282
  width: designTokens?.layout?.width?.desktop ?? "100%",
755
1283
  p: 2
756
1284
  };
757
- let backdropColor = "rgba(0, 0, 0, 0.4)";
758
1285
  const backdropToken = designTokens?.layout?.backdrop;
759
- if (backdropToken === false) {
760
- backdropColor = "transparent";
761
- } else if (typeof backdropToken === "string") {
762
- backdropColor = backdropToken;
763
- }
764
- if (blocking) {
1286
+ const resolveBackdropColor = (theme) => {
1287
+ if (backdropToken === false) return "transparent";
1288
+ if (typeof backdropToken === "string") {
1289
+ if (backdropToken.toLowerCase() === "auto") {
1290
+ const isDark2 = theme?.palette?.mode === "dark";
1291
+ return isDark2 ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.4)";
1292
+ }
1293
+ return backdropToken;
1294
+ }
1295
+ const isDark = theme?.palette?.mode === "dark";
1296
+ return isDark ? "rgba(255, 255, 255, 0.12)" : "rgba(0, 0, 0, 0.4)";
1297
+ };
1298
+ const isSafeRoute = (() => {
1299
+ try {
1300
+ if (typeof window === "undefined") return false;
1301
+ const current = new URL(window.location.href);
1302
+ const safeUrls = [policyLinkUrl, termsLinkUrl].filter(Boolean);
1303
+ return safeUrls.some((u) => {
1304
+ try {
1305
+ const target = new URL(u, current.origin);
1306
+ return target.pathname === current.pathname;
1307
+ } catch {
1308
+ return false;
1309
+ }
1310
+ });
1311
+ } catch {
1312
+ return false;
1313
+ }
1314
+ })();
1315
+ const effectiveBlocking = blocking && !isSafeRoute;
1316
+ if (effectiveBlocking) {
765
1317
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
766
1318
  /* @__PURE__ */ jsx4(
767
1319
  Box,
768
1320
  {
769
- sx: {
1321
+ sx: (theme) => ({
770
1322
  position: "fixed",
771
1323
  top: 0,
772
1324
  left: 0,
773
1325
  right: 0,
774
1326
  bottom: 0,
775
- backgroundColor: backdropColor,
1327
+ backgroundColor: resolveBackdropColor(theme),
776
1328
  zIndex: 1299
777
- }
1329
+ })
778
1330
  }
779
1331
  ),
780
1332
  /* @__PURE__ */ jsx4(Box, { sx: positionStyle, children: bannerContent })
@@ -885,7 +1437,7 @@ function FloatingPreferencesButton({
885
1437
  // src/context/ConsentContext.tsx
886
1438
  import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
887
1439
  var PreferencesModal = React4.lazy(
888
- () => import("./PreferencesModal-D2SEVH3N.js").then((m) => ({
1440
+ () => import("./PreferencesModal-RNRD3JKB.js").then((m) => ({
889
1441
  default: m.PreferencesModal
890
1442
  }))
891
1443
  );
@@ -1026,7 +1578,9 @@ function ConsentProvider({
1026
1578
  onPreferencesSaved,
1027
1579
  cookie: cookieOpts,
1028
1580
  disableDeveloperGuidance,
1029
- children
1581
+ guidanceConfig,
1582
+ children,
1583
+ disableDiscoveryLog
1030
1584
  }) {
1031
1585
  const texts = React4.useMemo(() => ({ ...DEFAULT_TEXTS, ...textsProp ?? {} }), [textsProp]);
1032
1586
  const cookie = React4.useMemo(
@@ -1038,7 +1592,15 @@ function ConsentProvider({
1038
1592
  if (categories) return categories;
1039
1593
  return DEFAULT_PROJECT_CATEGORIES;
1040
1594
  }, [categories]);
1041
- useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance);
1595
+ useDeveloperGuidance(finalCategoriesConfig, disableDeveloperGuidance, guidanceConfig);
1596
+ React4.useEffect(() => {
1597
+ const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
1598
+ if (!isProd && PreferencesModalComponent) {
1599
+ console.info(
1600
+ "[LGPD-CONSENT] Dica: seu PreferencesModal \xE9 customizado. Garanta exibir os detalhes dos cookies por categoria (nome, finalidade, dura\xE7\xE3o) usando as APIs setCookieCatalogOverrides / setCookieCategoryOverrides e getCookiesInfoForCategory. Consulte QUICKSTART e INTEGRACOES.md."
1601
+ );
1602
+ }
1603
+ }, [PreferencesModalComponent]);
1042
1604
  const boot = React4.useMemo(() => {
1043
1605
  if (initialState) return { ...initialState, isModalOpen: false };
1044
1606
  return createFullConsentState(
@@ -1122,6 +1684,7 @@ function ConsentProvider({
1122
1684
  {
1123
1685
  config: finalCategoriesConfig,
1124
1686
  disableDeveloperGuidance,
1687
+ disableDiscoveryLog,
1125
1688
  children: [
1126
1689
  children,
1127
1690
  /* @__PURE__ */ jsx6(React4.Suspense, { fallback: null, children: PreferencesModalComponent ? /* @__PURE__ */ jsx6(
@@ -1236,26 +1799,31 @@ function useConsentTexts() {
1236
1799
  function useConsentHydration() {
1237
1800
  return useConsentHydrationInternal();
1238
1801
  }
1802
+ var globalOpenPreferences = null;
1803
+ function _registerGlobalOpenPreferences(openPreferences) {
1804
+ globalOpenPreferences = openPreferences;
1805
+ }
1806
+ function _unregisterGlobalOpenPreferences() {
1807
+ globalOpenPreferences = null;
1808
+ }
1239
1809
  function useOpenPreferencesModal() {
1240
- const { openPreferences } = useConsent();
1241
- return openPreferences;
1810
+ const actions = useConsentActionsInternal();
1811
+ if (!actions) {
1812
+ throw new Error(
1813
+ "[LGPD-CONSENT] useOpenPreferencesModal deve ser usado dentro do ConsentProvider. Envolva seu componente com <ConsentProvider>."
1814
+ );
1815
+ }
1816
+ return actions.openPreferences;
1242
1817
  }
1243
- var globalOpenPreferences = null;
1244
1818
  function openPreferencesModal() {
1245
1819
  if (globalOpenPreferences) {
1246
1820
  globalOpenPreferences();
1247
1821
  } else {
1248
1822
  logger.warn(
1249
- "openPreferencesModal: ConsentProvider n\xE3o foi inicializado ou n\xE3o est\xE1 dispon\xEDvel."
1823
+ "openPreferencesModal called but no ConsentProvider is mounted. Make sure ConsentProvider is rendered before calling this function."
1250
1824
  );
1251
1825
  }
1252
1826
  }
1253
- function _registerGlobalOpenPreferences(openPreferences) {
1254
- globalOpenPreferences = openPreferences;
1255
- }
1256
- function _unregisterGlobalOpenPreferences() {
1257
- globalOpenPreferences = null;
1258
- }
1259
1827
 
1260
1828
  // src/components/PreferencesModal.tsx
1261
1829
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -1266,8 +1834,8 @@ function PreferencesModal2({
1266
1834
  const { preferences, setPreferences, closePreferences, isModalOpen } = useConsent();
1267
1835
  const texts = useConsentTexts();
1268
1836
  const designTokens = useDesignTokens();
1269
- const { toggleableCategories } = useCategories();
1270
- const [tempPreferences, setTempPreferences] = useState2(() => {
1837
+ const { toggleableCategories, allCategories } = useCategories();
1838
+ const [tempPreferences, setTempPreferences] = useState3(() => {
1271
1839
  const initialPrefs = { necessary: true };
1272
1840
  toggleableCategories.forEach((category) => {
1273
1841
  initialPrefs[category.id] = preferences[category.id] ?? false;
@@ -1291,43 +1859,126 @@ function PreferencesModal2({
1291
1859
  setTempPreferences(preferences);
1292
1860
  closePreferences();
1293
1861
  };
1862
+ const modalTitleSx = (theme) => ({
1863
+ fontSize: designTokens?.typography?.fontSize?.modal ?? void 0,
1864
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1865
+ });
1866
+ const modalContentSx = (theme) => ({
1867
+ p: designTokens?.spacing?.padding?.modal ?? void 0,
1868
+ backgroundColor: designTokens?.colors?.background ?? theme.palette.background.paper,
1869
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1870
+ });
1294
1871
  return /* @__PURE__ */ jsxs4(Dialog, { "aria-labelledby": "cookie-pref-title", open, onClose: handleCancel, ...DialogProps2, children: [
1295
- /* @__PURE__ */ jsx7(
1296
- DialogTitle,
1297
- {
1298
- id: "cookie-pref-title",
1299
- sx: { fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1300
- children: texts.modalTitle
1301
- }
1302
- ),
1303
- /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, sx: { p: designTokens?.spacing?.padding?.modal ?? void 0 }, children: [
1872
+ /* @__PURE__ */ jsx7(DialogTitle, { id: "cookie-pref-title", sx: modalTitleSx, children: texts.modalTitle }),
1873
+ /* @__PURE__ */ jsxs4(DialogContent, { dividers: true, sx: modalContentSx, children: [
1304
1874
  /* @__PURE__ */ jsx7(
1305
1875
  Typography3,
1306
1876
  {
1307
1877
  variant: "body2",
1308
- sx: { mb: 2, fontSize: designTokens?.typography?.fontSize?.modal ?? void 0 },
1878
+ sx: (theme) => ({
1879
+ mb: 2,
1880
+ fontSize: designTokens?.typography?.fontSize?.modal ?? void 0,
1881
+ color: designTokens?.colors?.text ?? theme.palette.text.primary
1882
+ }),
1309
1883
  children: texts.modalIntro
1310
1884
  }
1311
1885
  ),
1312
1886
  /* @__PURE__ */ jsxs4(FormGroup, { children: [
1313
- toggleableCategories.map((category) => /* @__PURE__ */ jsx7(
1314
- FormControlLabel,
1315
- {
1316
- control: /* @__PURE__ */ jsx7(
1317
- Switch,
1887
+ toggleableCategories.map((category) => {
1888
+ const full = allCategories.find((c) => c.id === category.id);
1889
+ const namesFromGuidance = full?.cookies ?? [];
1890
+ const used = globalThis.__LGPD_USED_INTEGRATIONS__ || [];
1891
+ const descriptors = getCookiesInfoForCategory(category.id, used);
1892
+ const enrichedDescriptors = descriptors.map((desc) => {
1893
+ if (desc.purpose && desc.duration && desc.provider) {
1894
+ return desc;
1895
+ }
1896
+ return {
1897
+ name: desc.name,
1898
+ purpose: desc.purpose || "-",
1899
+ duration: desc.duration || "-",
1900
+ provider: desc.provider || "-"
1901
+ };
1902
+ });
1903
+ const merged = [
1904
+ ...enrichedDescriptors,
1905
+ ...namesFromGuidance.filter((n) => !enrichedDescriptors.find((d) => d.name === n)).map((n) => ({ name: n, purpose: "-", duration: "-", provider: "-" }))
1906
+ ];
1907
+ let mergedFinal = merged;
1908
+ try {
1909
+ if (merged.length === 0) {
1910
+ const gmap = globalThis.__LGPD_INTEGRATIONS_MAP__ || {};
1911
+ const scriptRows = Object.entries(gmap).filter(([, cat]) => cat === category.id).map(([id]) => ({
1912
+ name: `(script) ${id}`,
1913
+ purpose: "Script de integra\xE7\xE3o ativo",
1914
+ duration: "-",
1915
+ provider: "-"
1916
+ }));
1917
+ if (scriptRows.length > 0) mergedFinal = scriptRows;
1918
+ }
1919
+ } catch {
1920
+ }
1921
+ return /* @__PURE__ */ jsxs4(Box2, { sx: { mb: 1 }, children: [
1922
+ /* @__PURE__ */ jsx7(
1923
+ FormControlLabel,
1318
1924
  {
1319
- checked: tempPreferences[category.id] ?? false,
1320
- onChange: (e) => setTempPreferences((prev) => ({
1321
- ...prev,
1322
- [category.id]: e.target.checked
1323
- }))
1925
+ control: /* @__PURE__ */ jsx7(
1926
+ Switch,
1927
+ {
1928
+ checked: tempPreferences[category.id] ?? false,
1929
+ onChange: (e) => setTempPreferences((prev) => ({
1930
+ ...prev,
1931
+ [category.id]: e.target.checked
1932
+ }))
1933
+ }
1934
+ ),
1935
+ label: `${category.name} - ${category.description}`
1324
1936
  }
1325
1937
  ),
1326
- label: `${category.name} - ${category.description}`
1327
- },
1328
- category.id
1329
- )),
1330
- /* @__PURE__ */ jsx7(FormControlLabel, { control: /* @__PURE__ */ jsx7(Switch, { checked: true, disabled: true }), label: texts.necessaryAlwaysOn })
1938
+ /* @__PURE__ */ jsxs4("details", { style: { marginLeft: 48 }, children: [
1939
+ /* @__PURE__ */ jsx7("summary", { children: "Ver detalhes" }),
1940
+ /* @__PURE__ */ jsx7(Box2, { sx: { mt: 1 }, children: /* @__PURE__ */ jsxs4("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
1941
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
1942
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Cookie" }),
1943
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Finalidade" }),
1944
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Dura\xE7\xE3o" }),
1945
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Fornecedor" })
1946
+ ] }) }),
1947
+ /* @__PURE__ */ jsx7("tbody", { children: mergedFinal.map((d, idx) => /* @__PURE__ */ jsxs4("tr", { children: [
1948
+ /* @__PURE__ */ jsx7("td", { children: d.name }),
1949
+ /* @__PURE__ */ jsx7("td", { children: d.purpose }),
1950
+ /* @__PURE__ */ jsx7("td", { children: d.duration }),
1951
+ /* @__PURE__ */ jsx7("td", { children: d.provider })
1952
+ ] }, d.name + idx)) })
1953
+ ] }) })
1954
+ ] })
1955
+ ] }, category.id);
1956
+ }),
1957
+ /* @__PURE__ */ jsx7(FormControlLabel, { control: /* @__PURE__ */ jsx7(Switch, { checked: true, disabled: true }), label: texts.necessaryAlwaysOn }),
1958
+ /* @__PURE__ */ jsxs4("details", { style: { marginLeft: 48 }, children: [
1959
+ /* @__PURE__ */ jsx7("summary", { children: "Ver detalhes" }),
1960
+ /* @__PURE__ */ jsx7(Box2, { sx: { mt: 1 }, children: /* @__PURE__ */ jsxs4("table", { style: { width: "100%", borderCollapse: "collapse" }, children: [
1961
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
1962
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Cookie" }),
1963
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Finalidade" }),
1964
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Dura\xE7\xE3o" }),
1965
+ /* @__PURE__ */ jsx7("th", { style: { textAlign: "left" }, children: "Fornecedor" })
1966
+ ] }) }),
1967
+ /* @__PURE__ */ jsx7("tbody", { children: (() => {
1968
+ const used = globalThis.__LGPD_USED_INTEGRATIONS__ || [];
1969
+ const necessaryCookies = getCookiesInfoForCategory(
1970
+ "necessary",
1971
+ used
1972
+ );
1973
+ return necessaryCookies.map((d, idx) => /* @__PURE__ */ jsxs4("tr", { children: [
1974
+ /* @__PURE__ */ jsx7("td", { children: d.name }),
1975
+ /* @__PURE__ */ jsx7("td", { children: d.purpose || "-" }),
1976
+ /* @__PURE__ */ jsx7("td", { children: d.duration || "-" }),
1977
+ /* @__PURE__ */ jsx7("td", { children: d.provider || "-" })
1978
+ ] }, d.name + idx));
1979
+ })() })
1980
+ ] }) })
1981
+ ] })
1331
1982
  ] })
1332
1983
  ] }),
1333
1984
  /* @__PURE__ */ jsxs4(DialogActions, { children: [
@@ -1339,13 +1990,22 @@ function PreferencesModal2({
1339
1990
  }
1340
1991
 
1341
1992
  export {
1993
+ setCookieCatalogOverrides,
1994
+ setCookieCategoryOverrides,
1995
+ getCookiesInfoForCategory,
1996
+ discoverRuntimeCookies,
1997
+ detectConsentCookieName,
1998
+ categorizeDiscoveredCookies,
1999
+ LogLevel,
2000
+ logger,
2001
+ setDebugLogging,
1342
2002
  DEFAULT_PROJECT_CATEGORIES,
1343
2003
  analyzeDeveloperConfiguration,
2004
+ logDeveloperGuidance,
2005
+ useDeveloperGuidance,
2006
+ GUIDANCE_PRESETS,
1344
2007
  useCategories,
1345
2008
  useCategoryStatus,
1346
- LogLevel,
1347
- logger,
1348
- setDebugLogging,
1349
2009
  createProjectPreferences,
1350
2010
  validateProjectPreferences,
1351
2011
  getAllProjectCategories,